简体   繁体   中英

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

Below code is getting compiled in 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; statement:

  1. The compiler allocates space on the stack to hold the yet uninitialized value of variable p
  2. Then the compiler initializes p with its uninitialized value

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).
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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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