Is the following program a strictly-conforming C99 program?
c
Solution
Let's look at what the C99 standard has to say about it:
See 7.1.3, §1, clause 5:
Each identifier with file scope listed in any of the following subclauses [...] is reserved for use as a macro name and as an identifier with file scope in the same name space if any of its associated headers is included.
As you include `stdlib.h`, the name `malloc` is reserved for use as a macro name.
But 7.1.4, §1 allows using `#undef` on reserved names:
The use of `#undef` to remove any macro definition will also ensure that an actual function is referred to.
This makes it possible to re-`#define` `malloc`, which results in undefined behaviour according to 7.1.3, §2:
If the program [...] defines a reserved identifier as a macro name, the behavior is undefined.
Why does the standard make this restriction? Because other functions of the standard library may be implemented as function-like macros in terms of the original function, so hiding the declaration might break these other functions.
In practice, you should be fine as long as your definition of `malloc` satisfies all provisions the standard provides for the library function, which can be achieved by wrapping an actual call to `malloc()`.
Problem
The title nearly says it all, but I will restate the question... Is the following program a "strictly conforming program" under 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, e.g., 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. */ } ```