[心得] 空指标常数(null pointer constant)

楼主: wtchen (没有存在感的人)   2016-04-28 02:51:03
以下是板工的小小心得,准备补充13诫用。
若是有不对的地方,请各位鞭小力点 /(_ _)\
(板工很懒得上色,以后会放一份在板工新blog)
### 在C的情况(注意:C++不适用,C++的场合请看下一节) ###
根据C11 standard 6.3.2.3 里对空指标常数 (null pointer constant)的定义:
An integer constant expression with the value 0, or such an expression cast
to type void *, is called a null pointer constant.
也就是说,(void*)0 是空指标常数(null pointer constant),
而(int *)0 是型别为整数指标的空指标(null pointer),这两者是不一样的。
比较明显的分别是,空指标常数可以被设成任何型别指标的左值,
而空指标只能被设成同样型别指标的左值。
以下是一个比较清楚的例子:
int *a = 0; // 没问题,空指标常数
int *b = (int*) 0; // 没问题,左值是同型别的空指标
int *c = (void*) 0; // C没问题,左值是空指标常数,不过C++会挂
int *d = (long*) 0; // 爆了,左值跟右值不同型态
这边有另一个例子:
typedef void (*func)(void); // func f = void (*f)();
func a = 0; // 没事,a是空指标常数
func b = (void *)0; // C 没问题,C++会挂
func c = (void *)(void *)0; // C跟C++都看不懂
### 在C++的情况 ###
根据C++14 standard 4.10 里对空指标常数 (null pointer constant)的定义:
A null pointer constant is an integer literal (2.13.2) with value zero
**or**(以后为C++11后特有) a prvalue of type std::nullptr_t.
意思是说,它可以是0或 nullptr,所以以下的情况:
int x = NULL; // C++ 可能没问题(视版本而定),不过会造成误解
int* ptr = (void*)0; // C 没问题,C++会挂
int* ptr = nullptr; // C++11以后的正统用法,
也就是上述C++14 standard里的空指标常数
**int x = NULL** 为啥会在C++里造成误解?
因为C++有C没有的函数重载(function overloading),举例来说
void DoSomething(int x);
void DoSomething(char* x);
- NULL = 0: DoSomething(NULL)会呼叫void DoSomething(int x),即
DoSomething(0)。
- NULL=nullptr: 会呼叫void DoSomething(char* x),即DoSomething(nullptr)。
结论就是,C++11以后还是尽量用nullptr取代NULL吧!
### 参考资料 ###
- [comp.lang.c FAQ list · Question 5.2 ](http://c-faq.com/null/null2.html)
- [Is (int *)0 a null pointer?]
(http://stackoverflow.com/questions/21386995/is-int-0-a-null-pointer)
- [Why are NULL pointers defined differently in C and C++?]
(http://stackoverflow.com/questions/7016861/
why-are-null-pointers-defined-differently-in-c-and-c)
作者: Feis (永远睡不着 @@)   2016-04-28 04:03:00
...
作者: Frozenmouse (*冰之鼠*)   2016-04-28 10:22:00
应该是“赋值给”吧?这样写好像常数是lvalue一样简单来说C的标准就是定义了n和(void*)n为空指标常数的特例,其中n是值为0的integer const expr(void*)(void*)0会挂的真正原因是(void*)0的结果不是int const expr,所以整个结果非null ptr const你举的例子是不是有搞错lvalue和rvalue的方向…
作者: yvb   2016-04-28 18:12:00
func c = (void *)(void *)0; // C跟C++都看不懂 ???C 应该没问题吧??
作者: Frozenmouse (*冰之鼠*)   2016-04-28 18:26:00
它是 "can only be assigned to" 被动式别拆开啊Orz不过这个已经不是程式问题了(炸

Links booklink

Contact Us: admin [ a t ] ucptt.com