Is the following program a strictly compatible C99 program?

The title says almost everything, but I will repeat the question ...

Is the following program a “strictly relevant program” according to the C99 standard?

#include <stdlib.h> /* Removing any pre-existing macro definition, in case one should exist in the implementation. * Seems to be allowed under 7.1.3 para 3, as malloc does not begin with _X where X is any capital letter. * And 7.1.4 para 1 explicitly permits #undef of such macros. */ #ifdef malloc #undef malloc #endif /* Macro substitution has no impact on the external name malloc * which remains accessible, eg, via "(malloc)(s)". Such use of * macro substitution seems enabled by 7.1.4 para 1, but not specifically * mentioned otherwise. */ void * journalling_malloc(size_t size); #define malloc(s) ((journalling_malloc)(s)) int main(void) { return malloc(10) == NULL ? 1 : 0; /* Just for the sake of expanding the * macro one time, return as exit code * whether the allocation was performed. */ } 
+6
c
source share
4 answers

See what the C99 standard has to say about this:

See section 7.1.3, §1, section 5:

Each identifier with a file region specified in any of the following subclasses [...] is reserved for use as a macro name and as an identifier with a file region in the same namespace if any of the associated headers are included .

When you include stdlib.h , the name malloc reserved for use as a macro name.

But 7.1.4, § 1 allows you to use #undef for reserved names:

Using #undef to remove any macro definition also ensures that the actual function is called.

This allows you to restore #define malloc , which leads to undefined behavior in accordance with 7.1.3, §2:

If a program [...] defines a reserved identifier as a macro name, the behavior is undefined .

Why does the standard make this restriction? Since other functions of the standard library can be implemented as functional macros from the point of view of the original function, so hiding the declaration may violate these other functions.

In practice, you should be fine as long as your malloc definition meets all the requirements that the standard provides for a library function, which can be achieved by transferring the actual call to malloc() .

+11
source share

You want to change journalling_malloc(...) from void to void * , change the comments to // (because they comment on your undef) and add #endif next to the top, but otherwise it looks fine.

+3
source share

Will it work: Yes.

Does it fit: None.

According to standard C:

http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf

All names in the standard library are reserved (including malloc).

 7.1.3 Reserved identifiers Specifically: <quote>Each macro name in any of the following subclauses</quote> <quote>All identifiers with external linkage in any of the following subclauses</quote> 

Also, a strictly appropriate program will not be able to determine the names reserved for implementation (i.e., include reserved names and identifiers, those intended for current libraries and reserved for future use).

 7.1.3 (note 2) Specifically: <quote>If the program declares or defines an identifier in a context in which it is reserved or defines a reserved identifier as a macro name, the behavior is undefined.</quote> 

Thus, by definition: the definition of malloc () is incompatible, as this behavior is undefined (illegal).

+1
source share

Macro identifiers are proper names, and all library identifiers of any type are prohibited for smoothing for a macro, regardless of the language status of the macros.

§6.10.3 / 7

The identifier immediately after the definition is called the macro name. There is one namespace for macro names.

§7.1.3 / 1

Each identifier with a file area in any of the following subclauses (including the future direction library) is reserved for use as a macro name and as an identifier with a file size in the same namespace if any of the associated headers are included.

§7.1.3 / 2

If a program declares or defines an identifier in the context in which it is reserved (except as permitted by 7.1.4) or defines a reserved identifier as a macro name, the behavior is undefined.

0
source share

All Articles