下面的代码是在MinGw中编译的。它是如何编译的?如何分配尚未创建的变量?
int main()
{
int*p=p;
return 0;
}
答案 0 :(得分:5)
如何编译?
变量的声明点从其声明符的末尾开始,但在其初始化之前。这允许更合理的自引用声明,如
void * p = &p;
以及像你这样的未定义的初始化。
如何分配尚未创建的变量?
这里没有任何作业,只是初始化。
已创建变量(在为其分配存储空间的意义上),但未初始化。您可以从该存储中发生的任何不确定值初始化它,具有未定义的行为。
如果您要求,大多数编译器会发出有关使用未初始化值的警告或错误。
答案 1 :(得分:1)
让我们来看看int*p=p;
语句会发生什么:
因此,基本上代码应该没有问题,除了它为变量赋予一个未初始化的值。
实际上与以下代码没有太大区别:
int *q; // define a pointer and do not initialize it
int *p = q; // assign the value of the uninitizlized pointer to another pointer
答案 2 :(得分:0)
可能的结果("它编译成")将是一个未完全初始化的指针变量的声明(由于它不是使用,所以最终的结果将是"空主#34;)。
声明并初始化指针。到目前为止,这是一件普通而合法的事情。但是,它被初始化为自身,并且它的值仅在语句结束后(即分号的位置)处于有效的初始化状态之后。
不出所料,这使得语句未定义行为。
根据定义,调用未定义的行为原则上可能导致几乎所有事情(虽然经常引用戏剧效果,例如格式化硬盘或将计算机置于火上都会被夸大)。
编译器实际上可能会生成一个指令,将寄存器(或内存位置)移动到自身,这在大多数体系结构上都是无操作指令,但可能会导致硬件异常,从而在一些特殊的体系结构中杀死您的进程验证指针寄存器(如果"随机"值绝对是无效地址)。
但是编译器不会插入任何"格式的硬盘"语句。
在实践中,优化编译器现在经常假设&#34;当它们遇到未定义的行为时没有发生<#em> ,所以很可能编译器只会尊重声明,什么都不做。
从各方面来说,这是完全允许的,因为未定义的行为。此外,它是编译器最简单,最麻烦的选择。