2015-04-05 83 views
0

我通过从Understanding Unix/Linux Programming (Bruce Molay)一些示例代码工作,我已经看到了一个无效UTMP类型的定义:为什么c中使用复杂的空类型?

#define NULLUT ((struct utmp *)NULL) 

的方法,如用此空类型:

struct utmp *utmp_next() 
{ 
    ... 
    if (no_more_records) 
     return NULLUT; 
} 

而客户端代码检查无效UTMP这样:

int main() 
{ 
    ... 
    while ((utbufp = utmp_next()) != ((struct utmp *)NULL)) 
     do_something() 
} 

为什么不utmp_next()只返回NULL从这个方法去罚款stddef.h和while循环检查呢?

实际的书源文件所在的位置:

回答

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() 
+0

...也许笔者自定义的'NULL'前面用'(void *)0'表示,并使用上面的转换函数使它与C++编译器一起工作... = P – Mints97 2015-04-05 08:54:32

+1

@ Mints97:是的,有很多可能的*非常糟糕的原因。 – 2015-04-05 08:58:07

+0

'void main()'是我的错字:(我已经更新了,我还附加了一个链接到源文件。 – 2015-04-05 09:42:57