【问题标题】:Should `!var` or `var == NULL` be used?应该使用 `!var` 还是 `var == NULL`?
【发布时间】:2012-09-30 19:34:06
【问题描述】:

在测试NULL 时,我看到很多使用!var 的代码。有没有理由使用这种测试而不是更明确的var == NULL。同样,if (var) 是否是非空项目的正确测试?

【问题讨论】:

  • 出于形式上的原因,我更喜欢后者——它使意图更清晰。但两者都可以接受。
  • 发现了一个非常相似的问题:stackoverflow.com/questions/459743/is-null-always-false
  • 两者都是有效的,如果var 是一个指针对象,则表示相同的意思。就个人而言,我更喜欢var == NULL,因为它更明确。许多 C 程序员倾向于重视简洁而不是明确。

标签: c pointers


【解决方案1】:

两者的区别:

!var

var == NULL

在第二种情况下,如果var 不是指针类型并且NULL 是用强制转换定义的(如(void *) 0),编译器必须发出诊断。

另外(如 cmets 中的 @bitmask 所指出的)要使用 NULL 宏,您需要包含一个定义 NULL 宏的标准头。在 C 中,为方便起见,NULL 宏在多个标头中定义(例如 stddef.hstdio.hstdlib.hstring.h 等)。

否则这两个表达式是等价的,这只是一个口味问题。使用你觉得更舒服的那个。

对于您的第二个问题,if (var)if (var != NULL) 相同,但有上述区别。

【讨论】:

  • 请注意,您至少需要为 NULL 定义多个标头之一。
  • c-faq.com/null/ptrtest.htmlif(var) is equivalent to if(var != 0) 以及更多关于空指针的内容。这个问题不是已经问了吗?见stackoverflow.com/a/3825704/1273830somehome 有什么不同吗?
  • 但是如果NULL 被定义为0,它会产生no的不同,这是完全合法的。 (我认为 C++ 不允许这样的定义,但 C 允许。)
  • @KeithThompson 实际上,在 C++ 中,NULL 保证为 0。在这种情况下,C 和 C++ 是不同的。在C语言中,NULL可以是指针(void*)0,理论上也可以是完全不同的东西,只要翻译成空指针常量即可。
  • @Lundin:我其实知道;我写的时候把它倒过来了。 C 和 C++ 都需要 NULL 扩展为实现定义的空指针常量,但它们对“空指针常量”的定义不同。在 C 中,空指针常量是“一个值为 0 的整数常量表达式,或这种类型为 void * 的表达式”。在 C++ 中,它是“整数类型的整数常量表达式纯右值,其计算结果为零或 std::nullptr_t 类型的纯右值”;我认为nullptr_t 是该语言的最新成员。 #define NULL 0 在两种语言中都有效。
【解决方案2】:

var == NULL 版本有一个主要优点:它使编译器和静态分析器可以找到一个特定的常见错误。

假设“var”不是一个指针,而是一个分配的变量。 if(!var) 将是一个未被检测到的错误。

NULL 通常被声明为#define NULL ((void*)0)。该声明不是标准的强制性声明,而是最常见的声明之一。具有半体面类型检查的编译器将能够对如下代码产生警告:

int var = ...;
if(var == NULL)  // compiler warning, var is not a pointer

除了上述优点之外,不使用! 运算符在风格上也是正确的,因为它是一个逻辑运算符,旨在用于布尔变量,而不是指针。它只是工作,因为 C 没有强类型。

我建议在这件事上遵循 MISRA-C,它规定对 NULL 或零的检查应该明确。 if(x != NULL) 而不是 if(x)。这些规则的基本原理是更具可读性的代码。无论如何,它都会转换为相同的机器代码,因此使您的代码更易于阅读并没有什么坏处。

【讨论】:

    【解决方案3】:

    ISO/IEC 9899 标准规定:

    1. 就语言而言:具有值0 的整数常量表达式,或转换为void * 类型的此类表达式称为空指针常量。如果将空指针常量转换为指针类型,则生成的指针(称为空指针)保证与指向任何对象或函数的指针不相等。

    2. 对于库:NULL 是一个扩展为实现定义的空指针常量的宏。

    这意味着您给出的表达方式同样“正确”。偏爱一种形式而不是另一种形式的原因主要是品味问题。

    【讨论】:

    • 也就是说,如果您有一个最小的编译器,并且没有超出标准要求的警告。如果您有一个现代的,假设是 1991 年之后制造的,如果您尝试将非指针变量与 NULL 进行比较,您会收到编译器警告。
    【解决方案4】:

    来自 C 标准:

    算术类型和指针类型统称为标量类型

    一元 + 或 - 运算符的操作数应具有算术类型; ~ 运算符的 整数类型;的 !运算符,标量类型。

    逻辑否定运算符的结果!如果其操作数的值比较,则为 0 不等于 0,如果其操作数的值比较等于 0,则为 1。结果的类型为 int。 表达式 !E 等价于 (0==E)。

    所以,这应该回答你的问题。

    【讨论】:

    • 其实不然,除非你知道NULL是怎么定义的。
    猜你喜欢
    • 2011-10-17
    • 2021-12-24
    • 1970-01-01
    • 1970-01-01
    • 2021-05-24
    • 2021-12-24
    • 2012-03-12
    • 1970-01-01
    • 2011-08-08
    相关资源
    最近更新 更多