With my compiler, it looks like this:
Of course, pi[1] and &pi[1] are undefined behavior.
Setting a breakpoint on pi[1] = -4; and start the program:
This is the result with pi = &j; pi = &i; pi = &j; pi = &i;
Breakpoint 1, main (argc=1, argv=0x7fffffffe428) at tmp.c:12 12 pi[1] = -4; (gdb) p &j $1 = (int *) 0x7fffffffe334 (gdb) p &i $2 = (int *) 0x7fffffffe330 (gdb) p &pi $3 = (int **) 0x7fffffffe338 (gdb) p &pi[1] $4 = (int *) 0x7fffffffe334 (gdb) c Continuing. i = 100, j = -4, *pi = 100 [Inferior 1 (process 2890) exited normally] (gdb)
&pi[1] randomly points to j
This is the result without pi = &j; pi = &i; pi = &j; pi = &i;
12 pi[1] = -4; (gdb) p &j $1 = (int *) 0x7fffffffe33c (gdb) p &i $2 = (int *) 0x7fffffffe32c (gdb) p &pi $3 = (int **) 0x7fffffffe330 (gdb) p &pi[1] $4 = (int *) 0x7fffffffe330 (gdb) c Continuing. Program received signal SIGSEGV, Segmentation fault. 0x000000000040056d in main (argc=1, argv=0x7fffffffe428) at tmp.c:13 13 printf("i = %d, j = %d, *pi = %d\n", i, j, *pi); (gdb) p pi $5 = (int *) 0x7ffffffffffc
With pi[1] = -4 (0xfffffffc) pointer pi modified to indicate a page on which the process cannot be read, so a segmentation error occurs.
You did not print pi , &pi and &pi[1] (which is UB), which would be interesting.
The answer to your question:
The compiler can decide where and in what order it transfers the variables in the stack frame. When you change the source code of a function, the compiler may decide differently. In addition, &pi[1] can point anywhere, as this behavior is undefined.