简体   繁体   English

当我在c / cpp中执行int * p = p时会发生什么?

[英]What happens when I do int*p=p in c/cpp?

Below code is getting compiled in MinGw. 下面的代码正在MinGw中编译。 How does it get compiled? 如何编译? How is it possible to assign a variable which is not yet created? 如何分配尚未创建的变量?

 int main()
{
    int*p=p;
    return 0;
}

How does it get compiled? 如何编译?

The point of declaration of a variable starts at the end of its declarator, but before its initialiser. 变量的声明点始于其声明器的末尾,但始于其初始化器。 This allows more legitimate self-referential declarations like 这允许使用更多合法的自我引用声明,例如

void * p = &p;

as well as undefined initialisations like yours. 以及像您这样的未定义的初始化。

How is it possible to assign a variable which is not yet created? 如何分配尚未创建的变量?

There is no assignment here, just initialisation. 这里没有分配,只有初始化。

The variable has been created (in the sense of having storage allocated for it), but not initialised. 变量已创建(就分配了存储而言),但尚未初始化。 You initialise it from whatever indeterminate value happened to be in that storage, with undefined behaviour. 您可以使用存储在存储中的任何不确定值来初始化它,并且行为不确定。

Most compilers will give a warning or error about using uninitialised values, if you ask them to. 如果您要求使用未初始化的值,大多数编译器会给出警告或错误。

Let's take a look at what happens with the int*p=p; 让我们看一下int*p=p;会发生什么int*p=p; statement: 声明:

  1. The compiler allocates space on the stack to hold the yet uninitialized value of variable p 编译器在堆栈上分配空间以保存变量p的尚未初始化的值
  2. Then the compiler initializes p with its uninitialized value 然后,编译器使用其未初始化的值初始化p

So, essentially there should be no problem with the code except that it assigns a variable an uninitialized value. 因此,除了为变量分配未初始化的值之外,代码基本上应该没有问题。

Actually there is no much difference than the following code: 实际上,与以下代码没有太大区别:

int *q;        // define a pointer and do not initialize it
int *p = q;    // assign the value of the uninitizlized pointer to another pointer

The likely result ("what it compiles to") will be the declaration of a pointer variable that is not initialized at all (which is subsequently optimized out since it is not used, so the net result would be "empty main"). 可能的结果(“编译结果”)将是一个指针变量的声明,该变量根本没有初始化(由于未使用它,随后对其进行了优化,因此最终结果将是“空主”)。

The pointer is declared and initialized. 指针被声明和初始化。 So far, this is an ordinary and legal thing. 到目前为止,这是一件普通且合法的事情。 However, it is initialized to itself, and its value is only in a valid, initialized state after the end of the statement (that is, at the location of the semicolon). 然而,它被初始化为本身,其价值只在语句结束有效,初始化状态(即,在分号的位置)。
This, unsurprisingly, makes the statement undefined behavior. 毫不奇怪,这使语句具有不确定的行为。

By definition, invoking undefined behavior could in principle cause just about everything (although often quoted dramatic effects like formatting your harddrive or setting the computer on fire are exaggerated). 根据定义,调用未定义的行为原则上可能会导致几乎所有事情(尽管经常会引用格式化硬盘或使计算机着火的戏剧性效果)。

The compiler might actually generate an instruction that moves a register (or memory location) to itself, which would be a no-op instruction on most architectures, but could cause a hardware exception killing your process on some exotic architectures which have special validating registers for pointers (in case the "random" value is incidentially an invalid address). 编译器实际上可能会生成一条指令,将寄存器(或内存位置)移至自身,这在大多数体系结构上都是无操作指令,但可能会导致硬件异常,从而在某些具有特殊验证寄存器的奇异体系结构上杀死您的进程指针(如果“ random”值偶然是无效地址)。
The compiler will however not insert any "format harddisk" statements. 但是,编译器不会插入任何“格式硬盘”语句。

In practice, optimizing compilers will nowadays often assume "didn't happen" when they encounter undefined behavior, so it is most likely that the compiler will simply honor the declaration, and do nothing else. 在实践中,如今,优化编译器在遇到未定义的行为时通常会假设“没有发生” ,因此,编译器很可能只会遵守该声明, 而不执行其他任何操作。
This is, in every sense, perfectly allowable in the light of undefined behavior. 每种情况下,鉴于未定义的行为,这是完全允许的。 Further, it is the easiest and least troublesome option for the compiler. 此外,对于编译器而言,这是最简单,最麻烦的选择。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM