Pointers are not signed integers, being much more like unsigned integers. However, you're printing them out as if they were signed integers. On a 32-bit system, there are several things that are likely to be 32 bits long: int
, unsigned int
, float
, and pointers. You can't in general tell which these are just by looking at them, but they all mean different things. (As an experiment, you could pass various integers in and print them like floats and vice versa: it's bad practice in general but it can show you that different data types do mean different things.)
Functions that take a variable number of arguments ("variadic" functions) do so in a complicated sort of way. In particular, they don't check argument types. You can pass any arguments you like to printf()
and similar functions, but getting them to agree with the format specifier is your problem. This means that the function has no way of getting the type right (as it would if you passed a float
to a function like int foo(int)
).
Passing the wrong types of arguments leads to undefined behavior, and is particularly likely to lead to problems if you pass arguments of the wrong size. On most 64-bit systems, pointers are 64 bits and int
s are 32.
Therefore, you need to use the right thing in the format string. printf("%p", &a);
will print out the address of a
as a pointer, which is what you want. The standard requires something like printf("%p", (void *)&a);
, but as a practical matter that's unnecessary on any computer you are ever likely to encounter.