请考虑以下代码:
#include <iostream>
struct foo
{
// (a):
void bar() { std::cout << "gman was here" << std::endl; }
// (b):
void baz() { x = 5; }
int x;
};
int main()
{
foo* f = 0;
f->bar(); // (a)
f->baz(); // (b)
}
Run Code Online (Sandbox Code Playgroud)
我们期望(b)崩溃,因为x空指针没有相应的成员.在实践中,(a)不会崩溃,因为this从不使用指针.
因为(b)取消引用this指针((*this).x = 5;),并且this为null,程序进入未定义的行为,因为取消引用null总是被称为未定义的行为.
会(a)导致未定义的行为吗?如果两个函数(和x)都是静态的呢?
c++ standards-compliance null-pointer undefined-behavior language-lawyer
我一直认为只会if(p != NULL){..}做这项工作.但在阅读Stack Overflow问题后,似乎没有.
那么在吸收了那个说明NULL指针可能具有非零值的问题的所有讨论之后检查NULL指针的规范方法是什么?
int* p = 0;
int* q = &*p;
Run Code Online (Sandbox Code Playgroud)
这是未定义的行为吗?我浏览了一些相关问题,但这个具体方面没有显示出来.
我理解NULLC/C++中常量的用途,我理解它需要在内部以某种方式表示.
我的问题是:对于C/C++中的对象,0地址是否是无效的内存位置有一些根本原因吗?或者我们理论上是因为这次预订而"浪费"一个字节的内存?
好的,所以我知道技术上这是未定义的行为,但是,我在生产代码中不止一次地看到过这种情况.如果我错了,请纠正我,但我也听说有些人使用这个"功能"作为当前C++标准缺乏方面的合理替代,即无法获得地址(嗯,成员函数的真正偏移).例如,这不是PCRE(Perl兼容的正则表达式)库的流行实现:
#ifndef offsetof
#define offsetof(p_type,field) ((size_t)&(((p_type *)0)->field))
#endif
Run Code Online (Sandbox Code Playgroud)
人们可以争论在这样的情况下利用这种语言的微妙性是否有效,甚至是必要的,但我也看到过这样使用:
struct Result
{
void stat()
{
if(this)
// do something...
else
// do something else...
}
};
// ...somewhere else in the code...
((Result*)0)->stat();
Run Code Online (Sandbox Code Playgroud)
这很好用!它通过测试是否存在来避免空指针取消引用this,并且它不会尝试访问else块中的类成员.只要这些警卫到位,这是合法的代码,对吗?所以问题仍然存在:是否有一个实际的用例,人们可以从使用这样的结构中受益?我特别关注第二种情况,因为第一种情况更多是语言限制的解决方法.或者是吗?
PS.对C风格的演员表示抱歉,不幸的是,如果可以,人们仍然喜欢打字.