The code causes undefined behaviour in 4 different ways; it is certainly not "correct" or "acceptable" as some of the other answers seem to be suggesting.
Firstly, *ppi = 888;
attempts to assign an int
to an lvalue of type int *
. This violates the constraint 6.5.16.1/1 of the assignment operator which lists the types that may be assigned to each other; integer to pointer is not in the list.
Being a constraint violation, the compiler must issue a diagnostic and may refuse to compile the program. If the compiler does generate a binary then that is outside the scope of the C Standard, i.e. completely undefined.
Some compilers, in their default mode of operation, will issue the diagnostic and then proceed as if you had written *ppi = (int *)888;
. This brings us to the next set of issues.
The behaviour of casting 888
to int *
is implementation-defined. It might not be correctly aligned (causing undefined behaviour), and it might be a trap representation (also causing undefined behaviour). Furthermore, even if those conditions pass, there is no guarantee that (int *)888
has the same size or representation as (int)888
as your code relies on.
The next major issue is that the code violates the strict aliasing rule. The object declared as int c;
is written using the lvalue *ppi
which is an lvalue of type int *
; and int *
is not compatible with int
.
Yet another issue is that the write may write out of bounds. If int
is 4 bytes and int *
is 8 bytes, you tried to write 8 bytes into a 4-byte allocation.
Another problem from earlier in the program is that ppi = (int**)(&c);
will cause undefined behaviour if c
is not correctly aligned for int *
, e.g. perhaps the platform has 4-byte alignment for int
and 8-byte alignment for pointers.