我可以使用NULL代替0的值吗?

问题描述 投票:11回答:6

我是否可以使用NULL指针代替0的值?

或者这样做有什么问题吗?


例如,例如:

int i = NULL;

作为替代:

int i = 0;

作为实验,我编译了以下代码:

#include <stdio.h>

int main(void)
{
    int i = NULL;
    printf("%d",i);

    return 0;
}

输出:

0

事实上,它给了我这个警告,它完全是正确的:

warning: initialization makes integer from pointer without a cast [-Wint-conversion] 

但是结果仍然相等。


  • 我可能会由此陷入不确定的行为吗?
  • 是否可以通过这种方式与NULL一起使用?
  • 在算术表达式中使用NULL作为数值有什么错误吗?
  • 在那种情况下,C ++的结果和行为如何?

我已经阅读了What is the difference between NULL, '\0' and 0的答案,关于NULL\00之间的区别是什么,但是我没有从那里得到简洁的信息,如果它是完全可以允许的并且也是正确使用的话NULL作为要在赋值和其他算术运算中使用的值。

c++ c pointers null language-lawyer
6个回答
11
投票
不能假定将NULL与零互换使用。例如,在此代码示例中

char const* foo = "bar"; foo + 0; 不能用0替换NULL是有效的C程序,因为未定义两个指针之间的加法(更不用说不同的指针类型了)。由于违反约束,将导致发出诊断信息。 The operands for addition will not be valid

对于C ++,情况有所不同。缺少从void*到其他对象类型的隐式转换意味着NULL在C ++代码中历来被定义为0。在C ++ 03中,您可能会摆脱它。但是从C ++ 11开始,它可以合法地be defined as the nullptr keyword。由于nullptr可能未添加到指针类型,因此现在再次产生错误。


如果std::nullptr_t被定义为NULL,那么即使您的实验也变得无效。 nullptr没有转换为整数。这就是为什么它被认为是更安全的空指针常量。

11
投票
我允许使用NULL指针代替0值吗?

No,这样做是不安全的。 std::nullptr_t是一个空指针常量,其

可能具有类型NULL,但更通常具有类型int。该语言允许将指针转换为整数,但是它不提供在不进行强制转换的情况下执行此类转换的功能(尽管某些编译器将其作为扩展提供)。此外,尽管将空指针转换为整数以产生值0是很常见的,但标准并不能保证这样做。如果要使用类型void *和值0的常量,则将其拼写为int

我可能会由此陷入不确定的行为吗?
    是,在任何将0扩展为类型为NULL的值的实现上。该标准未定义您在此类实现上的行为,因此,其行为未定义。
  • 是否可以通过这种方式使用NULL?
    这是较差的样式,在某些系统上和某些情况下会损坏。由于您似乎正在使用GCC,因此如果使用void *选项进行编译,它将在您自己的示例中中断。
  • 在算术表达式中使用NULL作为数值是否有问题?
    是。完全不能保证有数值。如果您的意思是0,则写0,这不仅定义明确,而且更短,更清晰。
  • 在那种情况下,C ++的结果如何?
    C ++语言对转换的要求比C语言严格,并且对-Werror具有不同的规则,但是实现也可以提供扩展。同样,如果您的意思是0,那您应该写。

4
投票
我允许使用NULL指针代替0值吗?
NULL

规则在语言及其版本之间有所不同。在某些情况下,您

可以,而在某些情况下则不能。无论如何,您

不应。如果幸运的话,当您尝试编译时,甚至在更好的情况下,编译器将发出警告,但编译失败。

在C ++中,在C ++ 11之前(引自C ++ 03):

[lib.support.types]

NULL是此国际标准中的实现定义的C ++空指针常量。

将空指针常量用作整数几乎没有意义。但是...

[conv.ptr]

空指针常量是整数类型的整数常量表达式(5.19)rvalue,其值为零。

因此,即使它毫无意义,它在技术上也能正常工作。由于这种技术,您可能会遇到编写不良的程序,这些程序滥用int i = NULL;

自C ++ 11起(引自最新草案):

[conv.ptr]

空指针常量是值为零的整数文字([lex.icon])

或类型为std :: nullptr_­t的prvalue

A NULL不能转换为整数,因此根据语言实现的选择,将std​::​nullptr_­t用作整数只能有条件地工作。

P.S。 NULL是类型nullptr的prvalue。除非需要在C ++ 11之前的版本中编译程序,否则应始终使用std​::​nullptr_­t而不是nullptr

C有点不同(引自C11 N1548草案):


6.3.2.3语言/转换/其他操作数/指针

3值为0的整数常量表达式,

或此类类型转换为类型NULL

,称为空指针常量。 ...

因此,这种情况类似于C ++ 11之后的情况,即void *的使用取决于语言实现所做出的选择,有条件地起作用。


2
投票
免责声明:我不懂C ++。我的答案不打算在C ++的上下文中应用

[NULL是值为零的'\0',与int完全一样,只是100%。

0

在指针的上下文中,for (int k = 10; k > '\0'; k--) /* void */;
for (int k = 10; k > 0; k--) /* void */;
0等于100%:

NULL

都是100%等效的。

关于if (ptr) /* ... */; if (ptr != NULL) /* ... */; if (ptr != '\0') /* ... */; if (ptr != 0) /* ... */; 的注意事项


ptr + NULL的上下文是指针的

not

。没有定义使用C语言添加指针。可以将指针和整数相加(或相减)。在ptr + NULL中,如果ptr + NULLptr是指针,则另一个

必须为整数,因此NULL实际上是ptr + NULL(int)ptr + NULL,并取决于ptr + (int)NULL的定义和ptr可以预期以下几种行为:全部正常运行,警告指针和整数之间的转换,编译失败,...


1
投票

Q:如果NULL和0等价于null指针常量,我应该使用哪个?

A:仅在指针上下文中,NULLNULL是等效的。当需要另一种0时,应该使用0

not,即使它可能起作用,因为这样做会发送错误的样式信息。 (此外,ANSI允许NULL的定义为NULL,在非指针上下文中根本不起作用。)特别是,当需要ASCII空字符(NUL)时,请勿使用((void *)0)。提供您自己的定义

NULL

0
投票
是,尽管

may取决于实现,但需要强制转换。但是,是的,否则它是100%合法的。

尽管它确实是非常非常糟糕的风格(不用说?)。>http://c-faq.com/null/nullor0.html是或曾经是

实际上

不是C ++,它是C。但是,标准

does

与许多C传统一样,有两个子句([diff.null]和[support。类型[nullptr]),从技术上讲是NULL C ++。它是实现定义的空指针常量。因此,即使样式不好,它在技术上也尽可能地像C ++。正如NULL中指出的,可能的实现方式可以是footnote0,但not
0L(void*)0当然可以(标准没有明确说明,但它几乎是NULL0之后剩下的唯一选择)是0L。几乎从来没有这样,但这是合法的可能性。编译器向您显示的警告表明该编译器实际上不兼容(除非您以C模式进行编译)。因为,根据警告,它

did convert

空指针(不是nullptr,该指针将是nullptr,这将是截然不同的),因此,nullptr_t的定义显然是[C0 ],可能不是。

无论哪种方式,您都有两种可能的合法(即编译器未损坏)情况。无论哪种情况(现实情况),NULL都类似于(void*)0NULL,那么您可以将“零或一”

转换为整数,并且您可以使用。

或者0的确是0L。在这种情况下,您拥有一个独特的值,该值可以保证比较以及明确定义的转换from

整数,但不幸的是没有

to

整数。但是,它确实具有对NULL的明确定义的转换(导致nullptr),并且bool具有对角的明确定义的转换(导致false)。
很不幸,这是two转换,因此它不在[[conv]中指出的

“零或一”]之内。因此,如果您的实现将bool定义为0,那么您将必须添加显式强制类型转换才能使代码正确。

© www.soinside.com 2019 - 2024. All rights reserved.