我可以使用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
?NULL
作为数字值有什么问题吗?我已经阅读了What is the difference between NULL, '\0' and 0的答案,关于\0
,0
和NULL
之间的区别是什么,但是如果没有从中得到简洁的信息,完全可以使用{{1}}作为赋值和其他算术运算的值。
答案 0 :(得分:62)
我可以使用NULL指针代替0值吗?
否,这样做并不安全。 NULL
是一个空指针常量,可以的类型为int
,但更通常的类型为void *
(在C语言中),否则不是直接的可分配给int
(在C ++> = 11中)。两种语言都允许将指针转换为整数,但是它们不提供隐式执行的此类转换(尽管某些编译器将其作为扩展提供)。此外,尽管将空指针转换为整数以产生值0是很常见的,但标准并不能保证这样做。如果要使用类型为int
且值为0的常量,则将其拼写为0
。
- 我可能会由此陷入不确定的行为吗?
是的,在NULL
扩展为类型void *
或任何其他不能直接分配给int
的值的实现上。该标准并未定义您在此类实现上的行为,因此,其行为未定义。
- 是否可以通过这种方式使用NULL?
它的样式很差,在某些系统上和某些情况下会损坏。由于您似乎正在使用GCC,因此如果您使用-Werror
选项进行编译,它将破坏您自己的示例。
- 在运算表达式中使用NULL作为数字值有什么错误吗?
是的。完全不能保证有数值。如果您的意思是0,则写0,这不仅定义明确,而且更短,更清晰。
- 在这种情况下,C ++的结果如何?
C ++语言在转换方面比C语言更为严格,并且对NULL
具有不同的规则,但是实现也可以提供扩展。同样,如果您的意思是0,那您应该写。
答案 1 :(得分:21)
NULL
是一些空指针常量。在C语言中,它可以是值为0
的整数常量表达式,也可以是强制转换为void*
的表达式,后者的可能性更大。这意味着您不能假设将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。由于std::nullptr_t
可能未添加到指针类型,因此再次产生错误。
如果将NULL
定义为nullptr
,那么即使您的实验也无效。从std::nullptr_t
到整数没有转换。这就是为什么它被认为是更安全的空指针常量。
答案 2 :(得分:13)
我可以使用NULL指针代替0值吗?
int i = NULL;
规则在语言及其版本之间有所不同。在某些情况下,您可以,而在其他情况下则不能。无论如何,您不应。如果幸运的话,当您尝试编译器时会警告您,甚至更好,但编译失败。
在C ++中,在C ++ 11之前(引自C ++ 03):
[lib.support.types]
NULL是此国际标准中实现定义的C ++空指针常量。
使用空指针常量作为整数几乎没有意义。但是...
[conv.ptr]
空指针常量是整数类型的整数常量表达式(5.19)rvalue,其值为零。
因此,即使它是荒谬的,从技术上讲也可以正常工作。由于这种技术,您可能会遇到编写错误的程序,这些程序滥用NULL
。
自C ++ 11起(引自最新草案):
[conv.ptr]
空指针常量是值为零或std :: nullptr_t 类型的prvalue的整数文字([lex.icon])。
std::nullptr_t
不能转换为整数,因此将NULL
用作整数只能根据语言实现的选择而有条件地工作。
P.S。 nullptr
是类型std::nullptr_t
的prvalue。除非您需要在C ++ 11之前的版本中编译程序,否则应始终使用nullptr
而不是NULL
。
C有点不同(引自C11 N1548草案):
6.3.2.3语言/转换/其他操作数/指针
3值为0的整数常量表达式,或强制转换为
void *
的表达式,称为空指针常量。 ...
因此,情况类似于C ++ 11之后的版本,即根据语言实现的选择,有条件地滥用NULL
起作用。
答案 3 :(得分:5)
是,但是根据实现的不同,可能需要强制转换。但是是的,否则它是100%合法的。
尽管这确实是非常非常糟糕的风格(不用说?)。
NULL
实际上是(或者曾经是)不是C ++,而是C。然而,像许多C传统一样,标准 does 有两个子句( [diff.null]和[support.types.nullptr])从技术上讲是NULL
C ++。这是实现定义的空指针常量。因此,即使样式不好,它在技术上也尽可能地像C ++。
正如footnote中指出的那样,可能的实现方式可以是0
或0L
,但不是 (void*)0
。
NULL
当然可以(标准没有明确说明,但是在0
或0L
之后,它几乎是唯一的选择)是nullptr
。几乎从来没有这样,但这是合法的可能性。
编译器向您显示的警告表明该编译器实际上不兼容(除非您在C模式下编译)。因为,根据警告,它进行了转换一个空指针(不是nullptr
,该指针将是nullptr_t
,这将是截然不同的),因此显然NULL
确实是(void*)0
,可能不是。
无论哪种方式,您都有两种可能的合法情况(即编译器未损坏)。无论哪种情况(现实情况),NULL
都类似于0
或0L
,那么您将“零或一” 转换为整数,那么您就很好去。
或者NULL
的确是nullptr
。在这种情况下,您拥有一个独特的值,该值可以保证比较以及从到整数的明确定义的转换,但不幸的是,不能从到整数。但是,它确实有明确定义的对bool
的转换(导致false
),并且bool
有明确定义的对整数的转换(导致0
)
不幸的是,这是两次 转换,因此它不在[conv]中指出的“零或一” 之内。因此,如果您的实现将NULL
定义为nullptr
,那么您将必须添加一个显式强制类型转换才能使代码正确。
答案 4 :(得分:3)
来自C常见问题解答:
问:如果NULL和0等价于null指针常量,我应该使用哪个?
A:仅在指针上下文中
NULL
和0
是等效的。NULL
在需要另一种0时应不使用,即使它可能可行,因为这样做会发送错误的样式信息。 (此外,ANSI允许NULL的定义为((void *)0)
,在非指针上下文中根本不起作用。)尤其是当ASCII空字符(NUL)为NULL时,请勿使用NULL
。想要的。提供您自己的定义
答案 5 :(得分:2)
免责声明:我不了解C ++。我的答案并不打算在C ++的上下文中应用
'\0'
是值为{0的int
,与0
一样,仅为100%。
for (int k = 10; k > '\0'; k--) /* void */;
for (int k = 10; k > 0; k--) /* void */;
在指针的上下文中,0
和NULL
等于100%:
if (ptr) /* ... */;
if (ptr != NULL) /* ... */;
if (ptr != '\0') /* ... */;
if (ptr != 0) /* ... */;
都是100%等效的。
关于ptr + NULL
ptr + NULL
的上下文是不是指针的上下文。没有定义使用C语言添加指针。可以将指针和整数相加(或相减)。在ptr + NULL
中,如果ptr
或NULL
是指针,则另一个必须是整数,因此ptr + NULL
实际上是(int)ptr + NULL
或ptr + (int)NULL
,并根据ptr
和NULL
的定义,可以预期以下几种行为:都可以正常工作,警告指针和整数之间的转换,编译失败,... >
答案 6 :(得分:1)
否,不再首选使用NULL
(指针初始化的旧方法)。
从C ++ 11开始:
关键字nullptr
表示指针文字。它是std :: nullptr_t类型的prvalue。存在从nullptr
到任何指针类型以及指向成员类型的任何指针的空指针值的隐式转换。对于任何空指针常量(包括类型std::nullptr_t
以及宏NULL
),都存在类似的转换。
https://en.cppreference.com/w/cpp/language/nullptr
实际上, std :: nullptr_t 是空指针文字nullptr
的类型。这是一个独特的类型,它本身不是指针类型或指向成员类型的指针。
#include <cstddef>
#include <iostream>
void f(int* pi)
{
std::cout << "Pointer to integer overload\n";
}
void f(double* pd)
{
std::cout << "Pointer to double overload\n";
}
void f(std::nullptr_t nullp)
{
std::cout << "null pointer overload\n";
}
int main()
{
int* pi; double* pd;
f(pi);
f(pd);
f(nullptr); // would be ambiguous without void f(nullptr_t)
// f(0); // ambiguous call: all three functions are candidates
// f(NULL); // ambiguous if NULL is an integral null pointer constant
// (as is the case in most implementations)
}
输出:
Pointer to integer overload
Pointer to double overload
null pointer overload
答案 7 :(得分:-2)
是,
#include
int main()
{
int *ptr = NULL;
printf("The value of ptr is %u",ptr);
return 0
'enter code here`