I was reading an article on usage of size_t
and ptrdiff_t
data types here, when I came across this example:
The code:
int A = -2;
unsigned B = 1;
int array[5] = { 1, 2, 3, 4, 5 };
int *ptr = array + 3;
ptr = ptr + (A + B); //Error
printf("%i\n", *ptr);
I am unable to understand a couple of things. First, how can adding a signed
and an unsigned
number cast the enter result into unsigned
type? If the result is indeed 0xFFFFFFFF
of unsigned
type, why in a 32 bit system, while adding it with ptr
, will it be interpreted as ptr-1
, given that the number is actually unsigned
type and the leading 1 should not signify sign?
Second, why is the result different in 64 bit system?
Can anyone explain this please?
1. I am unable to understand a couple of things. First, how can adding a signed and an unsigned number cast the enter result into unsigned type?
This is defined by integer promotions and integer conversion rank.
In this case unsigned has a higher rank than int, therefore int is promoted to unsigned.
The conversion of int ( -2 ) to unsigned is performed as described:
2. If the result is indeed 0xFFFFFFFF of unsigned type, why in a 32 bit system, while adding it with ptr, will it be interpreted as ptr-1, given that the number is actually unsigned type and the leading 1 should not signify sign?
This is undefined behavior and should not be relied on, since C doesn't define pointer arithmetic overflow.
3. Second, why is the result different in 64 bit system?
( This assumes( as does the picture ) that int and unsigned are 4 bytes. )
The result of A and B is the same as described in 1., then that result is added to the pointer. Since the pointer is 8 bytes and assuming the addition doesn't overflow( it still could if ptr had a large address, giving the same undefined behavior as in 2. ) the result is an address.
This is undefined behavior because the pointer points way outside of the bounds of the array.