为什么 NULL 指针在 C 和 C++ 中的定义不同?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7016861/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why are NULL pointers defined differently in C and C++?
提问by mohit
In C, NULL
is defined as (void *)0
whereas in C++ it is 0
. Why is it so?
In C I can understand that if NULL
is not typecast to (void *)
then compilers may/may not generate warning. Other than this, is there any reason?
在 C 中,NULL
被定义为,(void *)0
而在 C++ 中,它是0
. 为什么会这样?在 CI 中可以理解,如果NULL
不是类型转换,(void *)
那么编译器可能/可能不会生成警告。除此之外,还有什么原因吗?
回答by templatetypedef
Back in C++03, a null pointer was defined by the ISO specification (§4.10/1) as
在 C++03 中,ISO 规范(第 4.10/1 节)将空指针定义为
A null pointer constant is an integral constant expression (5.19) rvalue of integer type that evaluates to zero.
空指针常量是整数类型的整数常量表达式 (5.19) 右值,其计算结果为零。
This is why in C++ you can write
这就是为什么在 C++ 中你可以写
int* ptr = 0;
In C, this rule is similar, but is a bit different (§6.3.2.3/3):
在 C 中,此规则类似,但略有不同(第 6.3.2.3/3 节):
An integer constant expression with the value 0, or such an expression cast to type
void *
, is called a null pointer constant.55) If a null pointer constant is converted to a pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function.
值为 0 的整数常量表达式,或转换为 type 的此类表达式
void *
,称为空指针常量。55) 如果将空指针常量转换为指针类型,则结果指针(称为空指针)保证为比较不等于指向任何对象或函数的指针。
Consequently, both
因此,两者
int* ptr = 0;
and
和
int* ptr = (void *)0
are legal. However, my guess is that the void*
cast is here so that statements like
是合法的。然而,我的猜测是void*
演员阵容在这里,所以像这样的陈述
int x = NULL;
produce a compiler warning on most systems. In C++, this wouldn't be legal because you can't implicitly convert a void*
to another pointer type implicitly without a cast. For example, this is illegal:
在大多数系统上产生编译器警告。在 C++ 中,这是不合法的,因为您不能在没有强制转换的void*
情况下将 a 隐式转换为另一种指针类型。例如,这是非法的:
int* ptr = (void*)0; // Legal C, illegal C++
However, this leads to issues because the code
但是,这会导致问题,因为代码
int x = NULL;
is legal C++. Because of this and the ensuing confusion (and another case, shown later), since C++11, there is a keyword nullptr
representing a null pointer:
是合法的 C++。由于这一点和随之而来的混乱(以及另一种情况,稍后展示),从 C++11 开始,有一个关键字nullptr
表示空指针:
int* ptr = nullptr;
This doesn't have any of the above problems.
这不存在上述任何问题。
The other advantage of nullptr
over 0 is that it plays better with the C++ type system. For example, suppose I have these two functions:
nullptr
over 0的另一个优点是它可以更好地与 C++ 类型系统配合使用。例如,假设我有这两个功能:
void DoSomething(int x);
void DoSomething(char* x);
If I call
如果我打电话
DoSomething(NULL);
It's equivalent to
它相当于
DoSomething(0);
which calls DoSomething(int)
instead of the expected DoSomething(char*)
. However, with nullptr
, I could write
它调用DoSomething(int)
而不是预期的DoSomething(char*)
. 但是,有了nullptr
,我可以写
DoSomething(nullptr);
And it will call the DoSomething(char*)
function as expected.
它将DoSomething(char*)
按预期调用该函数。
Similarly, suppose that I have a vector<Object*>
and want to set each element to be a null pointer. Using the std::fill
algorithm, I might try writing
同样,假设我有一个vector<Object*>
并且想要将每个元素设置为空指针。使用该std::fill
算法,我可能会尝试编写
std::fill(v.begin(), v.end(), NULL);
However, this doesn't compile, because the template system treats NULL
as an int
and not a pointer. To fix this, I would have to write
但是,这不会编译,因为模板系统将其NULL
视为int
指针而不是指针。为了解决这个问题,我必须写
std::fill(v.begin(), v.end(), (Object*)NULL);
This is ugly and somewhat defeats the purpose of the template system. To fix this, I can use nullptr
:
这很丑陋,并且在某种程度上违背了模板系统的目的。为了解决这个问题,我可以使用nullptr
:
std::fill(v.begin(), v.end(), nullptr);
And since nullptr
is known to have a type corresponding to a null pointer (specifically, std::nullptr_t
), this will compile correctly.
并且由于nullptr
已知具有对应于空指针的类型(特别是std::nullptr_t
),这将正确编译。
Hope this helps!
希望这可以帮助!
回答by Keith Thompson
In C, NULL
expands to an implementation-defined "null pointer constant". A null pointer constant is either an integer constant expression with the value 0, or such an expression cast to void*
. So a C implementation may define NULL
either as 0
or as ((void*)0)
.
在 C 中,NULL
扩展为实现定义的“空指针常量”。空指针常量要么是值为 0 的整数常量表达式,要么是转换为 的表达式void*
。因此,C 实现可以定义NULL
as0
或 as ((void*)0)
。
In C++, the rules for null pointer constants are different. In particular, ((void*)0)
is not a C++ null pointer constant, so a C++ implementation can't define NULL
that way.
在 C++ 中,空指针常量的规则是不同的。特别是,((void*)0)
不是 C++ 空指针常量,因此 C++ 实现不能以NULL
这种方式定义。
回答by Jay
The C language was created to make it easier to program microprocessors. A C pointer is used to store the address of data in memory. A way was needed to represent that a pointer had no valid value. The address zero was chosen since all microprocessors used that address for booting up. Since it couldn't be used for anything else zero was a good choice to represent a pointer with no valid value. C++ is backward compatible with C so it's inherited that convention.
创建 C 语言是为了更容易地对微处理器进行编程。AC指针用于存储数据在内存中的地址。需要一种方法来表示指针没有有效值。选择地址零是因为所有微处理器都使用该地址进行启动。因为它不能用于其他任何东西,所以零是表示没有有效值的指针的好选择。C++ 向后兼容 C,因此它继承了该约定。
The requirement of casting zero when used as a pointer is only a recent add on. Later generations of C wanted to have more rigor (and hopefully fewer errors) so they started being more pedantic about syntax.
用作指针时强制转换为零的要求只是最近的一个添加。后代的 C 想要更严格(希望错误更少),所以他们开始对语法更加迂腐。