[英]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.