简体   繁体   English

以下程序是否严格符合C99程序?

[英]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? 以下程序是C99标准下的“严格符合程序”吗?

#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: 让我们看看C99标准对此有何评论:

See 7.1.3, §1, clause 5: 参见7.1.3§1第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. 当您包含stdlib.h ,名称malloc被保留以用作宏名称。

But 7.1.4, §1 allows using #undef on reserved names: 但是在7.1.4中,§1允许对保留名称使用#undef

The use of #undef to remove any macro definition will also ensure that an actual function is referred to. 使用#undef删除任何宏定义也将确保引用实际函数。

This makes it possible to re- #define malloc , which results in undefined behaviour according to 7.1.3, §2: 这使得可以重新定义#define malloc ,从而导致根据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() . 实际上,只要您对malloc的定义满足标准为库函数提供的所有规定,就可以了,可以通过包装对malloc()的实际调用来实现。

您将需要将journalling_malloc(...)void更改为void * ,将注释更改为//(因为它们正在注释掉您的undef),并在顶部附近添加#endif ,但是看起来还不错。

Will it work: Yes. 它会工作:是的。

Is it conformant: No. 是否符合:否

According to the C Standard: 根据C标准:

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

All names in the standard library are reserved (including malloc). 标准库中的所有名称都是保留的(包括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 (ie 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). 因此根据定义:定义malloc()是不符合规范的,因为它是未定义的行为(非法)。

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 §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 §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 §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. 如果程序在保留它的上下文中声明或定义标识符(而不是7.1.4允许),或者将保留标识符定义为宏名,则该行为未定义。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 PellesC是否严格符合标准C99? - Is PellesC strictly-conforming to standard C99? 宏定义数量超过 4095 - 程序不严格符合 ISO:C99 - Number of macro definitions exceeds 4095 - program does not conform strictly to ISO:C99 “container_of”宏可以严格遵守吗? - Can a "container_of" macro ever be strictly-conforming? 使用gcc,严格包含C99符号,特别是不包括POSIX - With gcc, include strictly C99 symbols, specifically excluding POSIX 使用C89和C99编译时,C程序在运行时的行为有何不同? - What C program behaves differently in run-time when compiled with C89 and C99? 使用MinGW将旧的C99程序转换为C11 - Converting old C99 program to C11 using MinGW 编译和链接C程序时,make忽略-std = c99标志 - make ignores -std=c99 flag when compiling and linking a C program Clang没有编译c11程序,理由是“隐含声明在c99中是非法的” - Clang fails to compile a c11 program, citing that “implicit declaration is illegal in c99” C 中的程序不写入文件并使用 -std=c99 发出警告 - Program in C dont write into the file and have warning with -std=c99 当在C89模式下编译时,以下程序如何输出`C89`和在C99模式下编译时输出`C99`? - How does the below program output `C89` when compiled in C89 mode and `C99` when compiled in C99 mode?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM