我正在阅读post,其中一个答案中有以下代码
#define goto { int x = *(int *)0; } goto
作者说,每次有人试图使用goto语句时,他的程序都会崩溃,我的问题是什么原因?根据我的理解,int x = *(int *)0;
将内存地址的前4个字节中的任何内容分配给x
,但为什么这肯定会使程序崩溃?
答案 0 :(得分:7)
只是因为您正在取消引用NULL
指针。但是 程序将崩溃的定义没有定义。 它可能会崩溃,可能不会崩溃或做一些奇怪的事情。这只是一种未定义的行为,并且最好避免。
值得注意的是goto
并非毫无用处。每个关键词都有自己的位置,语言作者和标准委员会的成员有理由继续维护它(考虑到语言正在发生一些戏剧性的变化)。如果明智地使用,goto在C和C ++中有一个值得的地方。
只是想知道这是一个UB,使用VC11,我编译了 在调试和发布模式下的上述代码段。在调试模式下,它崩溃但是 在发布模式下,编译器只是简化了语句并在那里 没有崩溃。
答案 1 :(得分:0)
在C或C ++中,内存地址0表示NULL指针。取消引用这样的指针总是未定义的行为,并且在大多数实现中它会引发分段错误,从而有效地“崩溃”程序。
答案 2 :(得分:0)
代码在两个方面给出了未定义的行为。
首先,重新定义语言关键字本身会产生未定义的行为。
其次,正如其他人所说,值为“0”的指针是NULL指针,并且取消引用它会给出未定义的行为。
因此,构造的实际结果是未定义的行为。未定义行为的常见症状是程序崩溃。但是,实际上并没有保证崩溃。它甚至不需要。
作为“为什么?”在编写宏观时,该代码的作者显然是“goto is evil”阵营的订阅者,并认为适合任意地对他人造成他/她不知情的偏见。实际上,goto
有其用途,即使通常更喜欢替代品。即使是Dijkstra(原始论文的作者,人们经常引用它来证明不使用goto
)只描述了肆无忌惮使用的问题,并没有声称它应该被简单地避免。 Donald Knuth后来在70年代中期写了一篇关于这个主题的论文,包括使用goto
是有益的例子。