开发者

Is the following program a strictly-conforming C99 program?

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. 
     */
}


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().


You will want to change journalling_malloc(...) from void to void *, change the comments to // (because they are commenting out your undef) and add a #endif near the top, but otherwise it looks fine.


Will it work: Yes.

Is it conformant: No.

According to the C Standard:

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 conforming program will can not define names that are reserved for the implementation (i.e. This includes reserved names and idnetifiers, those for current libraries and those 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: defining malloc() is non conformant because it is undefined behavior (Illegal).


Macro identifiers are proper names, and all library identifiers of any kind are forbidden from aliasing to a macro regardless of the linguistic status of macros.

§6.10.3/7

The identifier immediately following the define is called the macro name. There is one name space for macro names.

§7.1.3/1

Each identifier with file scope listed in any of the following subclauses (including the future library directions) 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.

§7.1.3/2

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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜