标题几乎说明了一切,但我会重申这个问题......
以下程序是否符合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.
*/
}
答案 0 :(得分:11)
让我们来看看C99标准对此有何看法:
见7.1.3,§1,第5条:
以下任何子条款[...]中列出的文件范围的每个标识符保留用作宏名称,并且作为具有相同名称空间的文件范围的标识符如果包含任何相关标题。
当您添加stdlib.h
时,名称malloc
将保留用作宏名称。
但是7.1.4,§1允许在保留名称上使用#undef
:
使用
#undef
删除任何宏定义也将确保一个 参考实际功能。
这使得重新#define
malloc
成为可能,根据7.1.3,§2:
如果程序[...]将保留标识符定义为宏名称,行为未定义。
为什么标准会制定此限制?因为标准库的其他函数可以在原始函数方面实现为类函数宏,所以隐藏声明可能会破坏这些其他函数。
在实践中,只要您的malloc
定义满足标准为库函数提供的所有条款,您就应该没问题,这可以通过将实际调用包装到malloc()
来实现。
答案 1 :(得分:3)
您需要将journalling_malloc(...)
从void
更改为void *
,将评论更改为//(因为他们正在评论您的undef)并在#endif
附近添加{{1}}顶部,但否则它看起来很好。
答案 2 :(得分:1)
它会起作用吗:是的。
符合标准:否。
根据C标准:
标准库中的所有名称都是保留的(包括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>
严格一致的程序也不能定义为实现保留的名称(即,这包括保留名称和标记符,当前库的名称和保留供将来使用的名称)。
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>
因此根据定义:定义malloc()是不符合的,因为它是未定义的行为(非法)。
答案 3 :(得分:0)
宏标识符是专有名称,无论宏的语言状态如何,都禁止任何类型的所有库标识符别名到宏。
§6.10.3/ 7
紧随其后的标识符 define被称为宏名称。 宏有一个名称空间 名。
§7.1.3/ 1
列出了文件范围的每个标识符 在以下任何子条款中 (包括未来的图书馆 方向)保留用作 宏名称和作为标识符 文件范围在同一名称空间中 任何相关的标题都是 包括在内。
§7.1.3/ 2
如果程序声明或定义了 标识符在其中的上下文中 保留(除了允许的) 7.1.4),或者将保留标识符定义为宏名称, 行为未定义。