13

I reading a C book. To print out a memory address of a variable, sometimes the book uses:

printf("%u\n",&n);

Sometimes, the author wrote:

printf("%d\n",&n);

The result is always the same, but I do not understand the differences between the two (I know %u for unsigned).

Can anyone elaborate on this, please?

Thanks a lot.

ipkiss
  • 13,311
  • 33
  • 88
  • 123
  • 1
    I would use `printf("%x\n",&n)` to print the hex representation of the address. But that's just me. – dappawit Mar 06 '11 at 04:15
  • 7
    Throw the book away - you shouldn't ever be using either `%u` or `%d` to print addresses, since an address may well have more bits than an int - use `%p`, or failing that `%#llx`. – Paul R Mar 06 '11 at 07:54
  • 1
    You also should cast the address to match the type of the specifier you choose. `printf` can't do any automatic conversions since the arguments do not have prototyped parameters. With `%p` that is `(void *)`, and with `%#llx` that is `(unsigned long long)`, etc. – M.M May 15 '14 at 04:25

5 Answers5

43

%u treats the integer as unsigned, whereas %d treats the integer as signed. If the integer is between 0 an INT_MAX (which is 231-1 on 32-bit systems), then the output is identical for both cases.

It only makes a difference if the integer is negative (for signed inputs) or between INT_MAX+1 and UINT_MAX (e.g. between 231 and 232-1). In that case, if you use the %d specifier, you'll get a negative number, whereas if you use %u, you'll get a large positive number.

Addresses only make sense as unsigned numbers, so there's never any reason to print them out as signed numbers. Furthermore, when they are printed out, they're usually printed in hexadecimal (with the %x format specifier), not decimal.

You should really just use the %p format specifier for addresses, though—it's guaranteed to work for all valid pointers. If you're on a system with 32-bit integers but 64-bit pointers, if you attempt to print a pointer with any of %d, %u, or %x without the ll length modifier, you'll get the wrong result for that and anything else that gets printed later (because printf only read 4 of the 8 bytes of the pointer argument); if you do add the ll length modifier, then you won't be portable to 32-bit systems.

Bottom line: always use %p for printing out pointers/addresses:

printf("The address of n is: %p\n", &n);
// Output (32-bit system): "The address of n is: 0xbffff9ec"
// Output (64-bit system): "The address of n is: 0x7fff5fbff96c"

The exact output format is implementation-defined (C99 §7.19.6.1/8), but it will almost always be printed as an unsigned hexadecimal number, usually with a leading 0x.

Adam Rosenfield
  • 390,455
  • 97
  • 512
  • 589
  • very well explained.Could you please give a one line e.g. of how to use %p format specifier. – Algorithmist Mar 06 '11 at 04:22
  • 2
    In C99 there are also several macros defined in `inttypes.h` which give you more flexibility when printing pointers. `%p` always prints a hexadecimal address. But suppose you wanted to print it in decimal (or octal!). `printf("Decimal: %" PRIuPTR ", Octal: %" PRIoPTR "\n", (uintptr_t)p, (uintptr_t)p);` – rlibby Mar 06 '11 at 04:35
  • The C book may have been written before %p was added to the lib. – typo.pl Mar 06 '11 at 04:49
  • @rlibby: Very true; however, since they're such a pain to use properly (and quite ugly, IMO), they're rarely used in practice. In 99.9% of the cases I've seen, pointers only get printed out for debugging purposes, in which case you know exactly the architecture you're running on, so there's nothing wrong with using `%08x` or `%016llx`. – Adam Rosenfield Mar 06 '11 at 04:52
  • @typo.pl: Quite likely. I believe (but am not certain) that the `%p` modifier was added in the 1999 version of the language standard (C99). – Adam Rosenfield Mar 06 '11 at 04:54
  • 1
    This post perhaps doesn't make it clear that both `%u` and `%d` cause undefined behaviour; and in general, using the wrong format specifier also causes undefined behaviour. It's not specified to "interpret the integer as unsigned", whatever that means; the printf function cannot detect what type you passed in and convert it to the correct type. A likely scenario (which this post describes) is that the compiler emits code which would read an unsigned int if you had passed an unsigned int in; so you end up with whichever unsigned int has the same bit pattern as the value you passed in. – M.M May 15 '14 at 04:31
1

%d and %u will print the same results when the most significant bit is not set. However, this isn't portable code at all, and is not good style. I hope your book is better than it seems from this example.

Raph Levien
  • 5,088
  • 25
  • 24
0

What value did you try? The difference unsigned vs. signed, just as you said you know. So what did it do and what did you expect?

Positive signed values look the same as unsigned so can I assume you used a smaller value to test? What about a negative value?

Finally, if you are trying to print the variable's address (as it appears you are), use %p instead.

Jonathan Wood
  • 65,341
  • 71
  • 269
  • 466
0

All addresses are unsigned 32-bit or 64-bit depending on machine (can't write to a negative address). The use of %d isn't appropriate, but will usually work. It is recommended to use %u or %ul.

steveo225
  • 11,394
  • 16
  • 62
  • 114
0

There is no such difference ,just don't get confused if u have just started learning pointers. %u is for unsigned ones.And %d for signed ones