Reputation:
in c, i tried to print out address of variable and address of some function. I got one is negative value, the other is positive value. My question is: why does C not represent in all negative or all positive value?
Here is my code:
int foo() {
return 0;
}
int main() {
int a;
printf("%d\n",&a);
printf("%d\n",foo);
return 0;
}
Here is result:
-1075908992 134513684
Upvotes: 12
Views: 18157
Reputation: 169583
Aside from using %p
, you could also cast to uintptr_t
to make sure to get an unisgned integer.
Use PRIuPTR
(or PRIXPTR
for hex) form <inttypes.h>
to get the correct format specifier:
printf("%" PRIuPTR "\n", (uintptr_t)(void *)&foo);
Upvotes: 0
Reputation: 108988
To be the most Standard conforming possible, pass "%p" in the format string to printf()
and cast the argument to void*
.
printf("%p\n", (void*)&a);
printf("%p\n", (void*)foo);
Quote from the Draft Standard (n1401.pdf)
7.20.6.1 The fprintf function 8 The conversion specifiers and their meanings are: p The argument shall be a pointer to void. The value of the pointer is converted to a sequence of printing characters, in an implementation-defined manner.
Upvotes: 8
Reputation: 57036
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.
Upvotes: 3
Reputation: 44804
printf isn't some magical interpretation tool. All it is doing if you give it "%d" is showing you what the bit pattern sitting in that variable looks like as an integer.
As to why some pointers are negative and some positive, all that means is that some have the high order bit set and some don't. What addresses are given to objects is really only the business of your operating system (usually with some hardware help). The programming language has no real say in it.
If I were you, I wouldn't be printing out addresses that way. If you really feel the need to look at them, use "%x" instead of "%d". That will print them in hex, which makes it much easier to figure out which bits are on and which ones aren't. Generaly all you are going to care about with addresses is if they are 0 or not, and if they match some other address's value.
Upvotes: 1
Reputation: 7127
You could also use printf("%p", &a)
as well. %p
is the pointer format specifier, to output the value of a pointer in an implementation-defined way. Practically speaking, its pretty much the same as %x, but would handle the case where a pointer is larger than an int.
Upvotes: 1
Reputation: 39480
You're printing out in decimal. You probably want to print out the memory location in hexadecimal (using "%p") (most memory addresses are shown in hexadecimal by convention).
Upvotes: 4
Reputation: 791859
Neither, a pointer doesn't have sign, but when converted to a signed integer it might be positive or negative.
Incidentally, passing a pointer to printf
with a format variable designed to print an integer causes undefined behaviour. You should always explicitly cast to the the correct type to get unspecified or implementation defined behaviour (depending on the cast).
Upvotes: 3
Reputation: 400274
Memory addresses should not be interpreted as signed integers in that way. The sign of the number depends on the highest bit set (assuming two's complement representation, which is used by the vast majority of systems currently in use), so a memory address above 0x80000000 on a 32-bit system will be negative, and a memory address below 0x80000000 will be positive. There's no real significance to that.
You should be printing memory addresses using the %p
modifier; alternatively, some people use %08x
for printing memory addresses (or %016llx
on 64-bit systems). This will always print out as an unsigned integer in hexadecimal, which is far more useful than a signed decimal integer.
int a;
printf("%p\n", &a);
Upvotes: 39
Reputation: 96869
You should pass the pointer formatter:
printf("%p\n",foo);
Upvotes: 7