Rob*_*rtS 77 c c++ null pointers language-lawyer
我可以使用NULL指针代替 的值0吗?
或者这样做有什么问题吗?
比如,例如:
int i = NULL;
Run Code Online (Sandbox Code Playgroud)
作为替代:
int i = 0;
Run Code Online (Sandbox Code Playgroud)
作为实验,我编译了以下代码:
#include <stdio.h>
int main(void)
{
int i = NULL;
printf("%d",i);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出:
0
Run Code Online (Sandbox Code Playgroud)
事实上,它给了我这个警告,这本身是完全正确的:
warning: initialization makes integer from pointer without a cast [-Wint-conversion]
Run Code Online (Sandbox Code Playgroud)
但结果仍然是等价的。
NULL吗?NULL在算术表达式中用作数值有什么问题吗?我已阅读的答案是什么NULL之间的区别,“\ 0”和0大约之间的区别是什么NULL,\0以及0是的,但我没有从那里简洁的信息,如果是很允许的,也是正确的使用NULL作为在赋值和其他算术运算中使用的值。
Joh*_*ger 84
我可以使用 NULL 指针代替 0 的值吗?
不,这样做是不安全的。 NULL是一个空指针常量,它可以具有 type int,但更典型的是具有 type void *(在 C 中),否则不能直接分配给 an int(在 C++ 中 >= 11)。这两种语言都允许将指针转换为整数,但它们不提供隐式执行的此类转换(尽管某些编译器将其作为扩展提供)。此外,虽然将空指针转换为整数以产生值 0 是很常见的,但标准并不保证这一点。如果你想要一个类型int和值为 0的常量,那么拼写它0。
- 我可能会因此而进入未定义行为吗?
是的,在任何NULL扩展为具有类型的值void *或任何其他不能直接分配给int. 该标准没有定义您对此类实现的赋值行为,因此其行为未定义。
- 是否允许以这种方式使用 NULL 进行操作?
这是一种糟糕的风格,它会在某些系统和某些情况下崩溃。由于您似乎在使用 GCC,如果您使用该-Werror选项进行编译,它会在您自己的示例中中断。
- 在算术表达式中使用 NULL 作为数值有什么问题吗?
是的。根本不保证有数值。如果你的意思是 0 那就写 0,这不仅定义明确,而且更短更清晰。
- 在这种情况下,C++ 的结果如何?
C++ 语言在转换方面比 C 更严格,并且对 有不同的规则NULL,但在那里,实现也可能提供扩展。同样,如果你的意思是 0 那么这就是你应该写的。
Sto*_*ica 32
NULL是一些空指针常量。在 C 中,它可能是一个带有 value 的整数常量表达式,也可能是一个转换0为 的表达式void*,后者更有可能。这意味着您不能假设NULL可以与零互换使用。例如,在此代码示例中
char const* foo = "bar";
foo + 0;
Run Code Online (Sandbox Code Playgroud)
替换0withNULL不能保证是一个有效的 C 程序,因为两个指针之间的加法(更不用说不同的指针类型)没有定义。由于违反约束,它将导致发出诊断。加法操作数将无效。
至于 C++,情况有些不同。缺乏从void*其他对象类型到其他对象类型的隐式转换意味着它NULL在历史上被定义为0C++ 代码。在 C++03 中,你可能会侥幸逃脱。但是从 C++11 开始,它可以合法地定义为nullptr关键字。现在再次产生错误,因为std::nullptr_t可能不会添加到指针类型。
如果NULL定义为nullptr那么即使您的实验也无效。没有从std::nullptr_t到整数的转换。这就是为什么它被认为是更安全的空指针常量。
eer*_*ika 22
我是否可以使用 NULL 指针代替 0 的值?
Run Code Online (Sandbox Code Playgroud)int i = NULL;
规则因语言及其版本而异。在某些情况下,您可以,而在其他情况下,您不能。无论如何,你不应该。如果你很幸运,你的编译器会在你尝试时发出警告,或者甚至更好,编译失败。
在 C++ 中,在 C++11 之前(引自 C++03):
[lib.support.types]
NULL 是此国际标准中实现定义的 C++ 空指针常量。
将空指针常量用作整数几乎没有意义。然而...
[转化率]
空指针常量是整数类型的整数常量表达式 (5.19) 右值,其计算结果为零。
因此,即使它是荒谬的,它在技术上也会起作用。由于这种技术性,您可能会遇到滥用NULL.
自 C++11(引自最新草案):
[转化率]
空指针常数是一个整数文字([lex.icon])与零值或类型的std的prvalue?::?nullptr_叔。
Astd?::?nullptr_t不能转换为整数,因此NULL作为整数使用只能有条件地工作,具体取决于语言实现所做的选择。
PSnullptr是类型的纯右值std?::?nullptr_t。除非您需要在 C++11 之前的版本中编译您的程序,否则您应该始终使用nullptr代替NULL.
C 有点不同(引自 C11 草案 N1548):
6.3.2.3 语言/转换/其他操作数/指针
3 值为 0 的整数常量表达式, 或转换为 type 的此类表达式
void *,称为空指针常量。...
因此,这种情况类似于 C++11 之后的情况,即NULL根据语言实现所做的选择,有条件地滥用作品。
Dam*_*mon 10
是的,但根据实现,您可能需要演员表。但是,是的,它是 100% 合法的,否则。
虽然它真的,真的,真的很糟糕的风格(不用说?)。
NULL是,或者过去,实际上不是 C++,而是 C。然而,与许多 C 遗留系统一样,该标准确实有两个子句([diff.null] 和 [support.types.nullptr]),它们在技术上构成了NULLC++。它是一个实现定义的空指针常量。因此,即使它的风格很糟糕,从技术上讲,它也与 C++ 一样。
正如脚注中所指出的,可能的实现可能是0或0L,但不是 (void*)0。
NULL当然可以(标准没有明确说明,但它几乎是0或之后剩下的唯一选择0L)是nullptr. 几乎从来没有这种情况,但这是一种合法的可能性。
编译器向您显示的警告表明编译器实际上不兼容(除非您在 C 模式下编译)。因为,好吧,根据警告,它确实转换了一个空指针(不是nullptr哪个是 of nullptr_t,哪个是不同的),所以显然 的定义NULL确实是(void*)0,它可能不是。
无论哪种方式,您都有两种可能的合法(即编译器未损坏)情况。要么(现实情况),NULL类似于0or 0L,那么您将“零或一”转换为整数,您就可以开始了。
或者NULL确实是nullptr。在这种情况下,你有一个大约有比较以及明确定义的转换担保鲜明的值从整数,但偏偏不给整数。然而,它确实有一个明确定义的到bool(导致false)的转换,并且bool有一个明确定义的到整数的转换(导致0)。
不幸的是,这是两次转换,所以它不在[conv] 中指出的“零或一”之内。因此,如果您的实现定义NULL为nullptr,那么您将必须为您的代码添加显式转换才能正确。
来自 C 常见问题解答:
问:如果 NULL 和 0 等价于空指针常量,我应该使用哪个?
答:只有在指针上下文中
NULL和0是等价的。NULL应该不是需要另一种为0时,可以使用,即使它可能会奏效,因为这样做发出了错误的文体消息。(此外,ANSI 允许 NULL 的定义为((void *)0),这在非指针上下文中根本不起作用。)特别是,NULL在需要 ASCII 空字符 (NUL) 时不要使用。提供您自己的定义
免责声明:我不懂 C++。我的回答并不意味着适用于 C++ 的上下文
'\0'是一个int零值,100% 完全像0.
for (int k = 10; k > '\0'; k--) /* void */;
for (int k = 10; k > 0; k--) /* void */;
Run Code Online (Sandbox Code Playgroud)
在 pointers 的上下文中,0和NULL100% 等效:
if (ptr) /* ... */;
if (ptr != NULL) /* ... */;
if (ptr != '\0') /* ... */;
if (ptr != 0) /* ... */;
Run Code Online (Sandbox Code Playgroud)
都是 100% 等价的。
注意事项 ptr + NULL
的情况下ptr + NULL是不是该指针。C语言中没有对指针相加的定义;指针和整数可以相加(或相减)。在ptr + NULL如果任一ptr或者NULL是一个指针,其他必须是一个整数,所以ptr + NULL是有效(int)ptr + NULL还是ptr + (int)NULL和根据的定义ptr和NULL一些行为可以预期:这一切工作,预警指针和整数,未能编译之间的转换,.. .
不,不再喜欢使用NULL(旧的指针初始化方式)。
从 C++11 开始:
关键字nullptr表示指针文字。它是 std::nullptr_t 类型的纯右值。存在从nullptr任何指针类型和任何指向成员类型的指针的空指针值的隐式转换。任何空指针常量都存在类似的转换,其中包括 typestd::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)
}
Run Code Online (Sandbox Code Playgroud)
输出:
Pointer to integer overload
Pointer to double overload
null pointer overload
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7224 次 |
| 最近记录: |