You are getting the warnings because you are using the wrong format specifier in printf()
. p
is an integer-pointer. &p
is the address of a pointer. &x
and &y
are addresses of integers. These are all addresses in memory, not values of a variable. The specifier %u
is for values of unsigned integers. So you are printing apples where the compiler expects oranges. Addresses are shorter than some values stored in variables. By using %u
will actually print an address value as decimal (highly unusual) and some more data located behind that in memory. The compiler is complaining, because that's probably not what you want to do. To print the addresses use the specifier %p
, as in:
printf("\n&x = %p\n",&x);
Aside from that, your variables are signed integers and as such should use %i
instead of %u
. The %u
format specifier of printf()
is for positive integers only. For small positive values both, %i
and %u
are interchangeable. The warning is displayed because the variable type does not match its specifier and this causes problems in some cases.
This would be more sensible from your variable types:
printf("\n\np = %p\n", p); // p is a pointer so %p would print the address
printf("\n*p = %i\n", *p); // the data saved at that address is an integer
// so %i is appropriate if you dereference the
// pointer with the star "*p"
printf("\n&x = %p\n", &x); // &x gives the address of the integer variable x
// so %p is the specifier for that address
printf("\n&y = %p\n", &y);
printf("\n&z = %p\n", &z);
printf("\n&p = %p\n\n", &p); // &p gives the address, where the pointer p is
// stored -> still an address -> %p is the right
// specifier
A bit background on signed and unsigned integers and pointers:
C uses the same 32 bit (or another power of two depending on the system architecture) to store unsigned and signed integers. Thus the highest unsigned int
is 232-1 or in binary notation:
232-1 = (11111111111111111111111111111111)2 <- (unsigned)
And a the number one would look like this in binary:
1 = (00000000000000000000000000000001)2 <- (unsigned)
Now regular signed integers need to store the negative numbers as well, but still in the same space of 32 bit. If you stored the sign, of the number in e.g. the first bit, you would loose a whole bit. That would be wasteful, e.g. the zero would have two representations as + and - zero. To circumvent this problem negative numbers in signed integers are stored a little differently: To encode a number into a signed integer, you add halve the possible range for your 32 bit number. This is 2(32-1), and then use the regular binary representation of that new number. So a one is encoded like 2(32-1) + 1 would be for an unsigned integer. We have:
2(32-1) = (11111111111111111111111111111111)2 <-signed
...
1 = (10000000000000000000000000000001)2 <- signed
0 = (10000000000000000000000000000000)2 <- signed
-1 = (01111111111111111111111111111111)2 <- signed
...
-2(32-1) = (00000000000000000000000000000000)2 <-signed
Now you have encoded the same number of integers, but the maximum for signed integers is consequently only 2(32-1) as opposed to double that, 232-1, for unsigned integers. This is called excess-K or offset-binary representation for negative numbers. Most systems use the Two's complement, where the first, most significant bit is reversed.
To see this, set x=-1;
and then printf("%u",x)
. You will get the following output:
2147483648
Which is 232-1 or (01111111111111111111111111111111)2 in binary notation. For the Two's complement this number would be:
4294967295
Or 232-1. This equals (11111111111111111111111111111111)2 in binary, so it has the first bit reversed compared to the above excess-K value of 2147483648.
So this is how the data is stored. Pointers come into play when you think of the where. The physical bits in the memory must have addresses. Since there are incredibly many of them you address them in chunks of more then one bit. If you create a pointer, the physical memory at the address of the pointer holds another address in memory. So a house is a physical object, much like a bit in your PC's memory. A piece of paper would be a pointer. It is smaller than the house, but can hold the address of a house or other houses. In that analogy, above you would have tried to demolish the piece of paper instead of the actual house and it was actually a mountain...
int *
andunsigned int
are not the same thing.