我正在处理来自Understanding Unix/Linux Programming (Bruce Molay)的一些示例代码,并且我已经看到了NULL utmp类型的定义:
#define NULLUT ((struct utmp *)NULL)
这种null类型用于以下方法:
struct utmp *utmp_next()
{
...
if (no_more_records)
return NULLUT;
}
客户端代码检查NULL utmp:
int main()
{
...
while (( utbufp = utmp_next() ) != ((struct utmp *)NULL) )
do_something()
}
为什么不让utmp_next()从NULL
中定义的方法返回stddef.h
,而while循环检查呢?
实际的图书源文件在这里:
答案 0 :(得分:4)
在大多数情况下,他们不是。大多数C程序员只使用NULL
宏,只在极少数情况下使用必要的指针类型。
通过定义类型特定的空指针宏,如
#define NULLUT ((struct utmp *)NULL)
你得到的东西只是那种特定的指针类型。比较不同类型的指针,例如:
char *ptr = some_value;
if (ptr == NULLUT) /* ERROR */
编译器将标记错误。另一方面,空指针常量与任何指针类型都是比较兼容的。
我想作者认为这是一个好主意。
我不同意。
宏NULL
是标准的,每个C程序员都会识别它。在比较,赋值,初始化或任何指针类型的return
语句中使用它是完全安全的。大多数情况下,使用指针参数作为函数的参数是非常安全的。唯一的例外是函数没有可见的原型(解决方案:总是使用原型),或者它是一个可变函数,如printf
(解决方案:强制NULL
到适当的指针类型)。 (使用新_Generic
功能的宏可能是另一种可能需要强制转换的情况。)
定义你自己的NULLUT
宏没有任何我能看到的真正目的。
while (( utbufp = utmp_next() ) != ((struct utmp *)NULL) )
do_something()
这是来自书中的另一个源文件(您在问题中引用的who3.c
)。在这里,作者甚至没有定义NULLUT
宏,而是选择编写
((struct utmp *)NULL)
这样写得更好:
while (( utbufp = utmp_next() ) != NULL) )
do_something()