我开始研究 glibc ( GNU Libc ) 以了解它是如何编写的。在malloc.c
中,我找到了一段代码如下:
#ifndef void
#define void void
#endif
有人可以向我解释这是什么意思吗?不void
总是定义的吗?
谢谢
查看git history,它是这样的:
/*
Void_t* is the pointer type that malloc should say it returns
*/
#ifndef Void_t
#if (__STD_C || defined(WIN32))
#define Void_t void
#else
#define Void_t char
#endif
#endif /*Void_t*/
这是历史 [C] 的解决方法,它没有void
并malloc()
返回char *
而不是void
. 该代码于 2011 年被 Ulrich Drepper 删除。提交似乎不是由脚本或任何自动生成的,因此他必须有这样定义的意图。
提交消息没有说明void
:
简化 malloc 代码
删除各种未使用的配置选项和死代码。
我不确定#define void void
in 的原因是什么malloc.c
,但我的猜测如下:
正如Yasushi Shoji 提到的,void
在 C 中并不总是一个关键字。当它被引入/标准化时,能够使用void
不支持它的编译器使用 new 关键字编译代码的常见解决方法是将其定义void
为宏,例如:
#define void int /* or maybe #define void char */
该宏定义可以使用编译器命令行而不是通过标题来完成,这样就不需要确保所有翻译单元都包含定义宏的标题。
但是,迁移到 new 关键字的程序员使用如下代码序列也可能很常见:
#ifndef void
#define void int
#endif
例如,您将看到以下代码:
/*
* This is a fairly bogus thing to do, but there seems to be no better way for
* compilers that don't understand void pointers.
*/
#ifndef void
#define void char
#endif
在http://buildbot.zope.org/Squid-2.4STABLE6%2B/include/snmp_impl.h?annotate=1.1.1.1&cvsroot=Zope.org
所以,我的猜测是#define void void
inmalloc.c
只是一种防止它包含的标题中可能存在的任何此类序列重新定义的方法,但仍然允许它之前已经被定义为“gloablly”(在之前void
只有注释)如果它是在不支持的配置上编译的。换句话说,如果在开始编译之前没有全局定义为宏,则没有理由在编译的后期将某些内容定义为其他内容。malloc.c
#define void void
void
void
malloc.c
尽管void
是 C 中的关键字,但关键字并未定义为预处理器符号。您引用的代码确保它也被定义为预处理器符号。
我不知道为什么这是必要的。
void
可能总是有意义的,但我会说 void通常不是#define
d。我不确切知道那里发生了什么,但是这段代码运行的结果是,如果#ifdef void
以后有人说,那将是真的。所以换句话说,它只会通过这次代码运行获得一次#define
。void