Search code examples
c++pointersmemory-addressdereference

Assign char address to an int pointer, and consequently write an int-size piece of memory


from the book Stroustrup - Programming: Principles and practices using C++. In §17.3, about Memory, addresses and pointers, it is supposed to be allowed to assign a char* to int*:

char ch1 = 'a';
char ch2 = 'b';
char ch3 = 'c';
char ch4 = 'd';
int* pi = &ch3;   // point to ch3, a char-size piece of memory
*pi = 12345;      // write to an int-size piece of memory
*pi = 67890;

graphically we have something like this:

char address to int pointer

quoting from the source:

Had the compiler allowed the code, we would have been writing 12345 to the memory starting at &ch3. That would definitely have changed the value of some nearby memory, such as ch2 or ch4, or we would have overwritten part of pi itself.

In that case, the next assignment *pi = 67890 would place 67890 in some completely different part of memory.


I don't understand, why the next assignment would place it: in some completely different part of memory? The address stored in int *pi is still &ch3, so that assignment would be overwrite the content at that address, i.e. 12345. Why it isn't so?

Please, can you help me? Many thanks!


Solution

  • char ch3 = 'c';
    int* pi = &ch3;
    

    it is supposed to be allowed to assign a char* to int*:

    Not quite - there is an alignment concern. It is undefined behavior (UB) when

    If the resulting pointer is not correctly aligned for the referenced type, the behavior is undefined. C17dr § 6.3.2.3 7

    Example: Some processor require int * to be even and if &ch3 was odd, storing the address might fail, and de-referencing the address certainly fails: bus error.


    The next is certainly UB as the destination is outside the memory of ch3.
    ch1, ch2, ch4 might be nearby and provide some reasonable undefined behavior, but the result is UB.

    // undefined behavior
    *pi = 12345;      // write to an int-size piece of memory`
    

    When code attempts to write outside its bounds - it is UB, anything may happen, including writing into neighboring data.

    The address stored in int *pi is still &ch3

    Maybe, maybe not. UB has occurred.

    why the next assignment would place it: in some completely different part of memory?

    The abusive code suggests that pi itself is overwritten by *pi = 12345;. This might happen, it might not. It is UB. A subsequent use of *pi is simply more UB.


    Recall with UB you might get what you hope for, you might not - it is not defined by C.