所以有问题的代码行是:
*((int*)(0))=1;
因为我对C / C ++的经验很少而且没有非常努力,所以我不明白这个简单的表达方式。它究竟意味着什么?
答案 0 :(得分:28)
它意味着崩溃程序,通常在调试期间很有用。
它取消引用NULL指针并尝试为该内存分配一个值,理论上这只是未定义的行为,但会导致99%的系统出现访问冲突异常。
通常,它可以在以下情况中找到:
if ( !FileRead(importantFile) )
{
// this should never happen, critical exception
*((int*)(0))=1;
}
答案 1 :(得分:11)
一点一点地分解。在左侧的外部括号内,您有:
(int*)(0)
这是一个值为0的C样式转换为指向int的指针;创建一个空指针,实际上。
让我们添加一个变量来捕获第一个表达式的结果:
int* x = (int*)(0);
外部现在是:
*(x) = 1;
这是取消引用指针x,并为结果int赋值。
由于(在这种情况下)x是一个空指针,这将在取消引用时崩溃(严格来说,它将在取消引用后的赋值中崩溃 - 请参阅下面的注释)。它通常用于强制崩溃或其他依赖于系统的未定义行为;通常用于测试或调试目的。您不希望在生产代码中使用这样的行。
注意:有一些体系结构,通常在嵌入式系统中,其中零是有效的内存地址,上面的代码可能有合法的用途。但是,如果您正在使用这样的平台,那么您不太可能在问题中使用语法。
答案 2 :(得分:9)
正如其他人所说,这是一种放入调试器的方法。大多数计算机都拒绝写入内存地址0
,而是会进入某种诊断模式。
但是,更好的选择是来自raise()
或<signal.h>
的标准函数<csignal>
。 raise( SIGSEGV )
将产生与您的示例相同的结果,即使在执行允许写入地址为零的计算机上(此类计算机确实存在!)和编译器具有对未定义行为的自由解释。该操作不会保证或必需崩溃。从编译器的角度来看,它可能什么也不做,只是从编译的程序中删除它就不错了。
有关更具描述性的信号值,请参阅man signal
。意思是raise( SIGTRAP )
或abort()
。后者在我的系统上相当于raise( SIGABRT )
,但我很懒,检查POSIX或C语言是否保证了等效性。
答案 3 :(得分:2)
这会在null指针处存储一些东西(并导致SEGFAULT)。用于在保留所有内存内容等的同时停止程序并调用调试器。
答案 4 :(得分:2)
此*((int*)(0))=1;
等于
int *p=NULL;
*p=1;