为什么在c中使用复杂的null类型?

时间:2015-04-05 08:26:10

标签: c

我正在处理来自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循环检查呢?

实际的图书源文件在这里:

1 个答案:

答案 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()