C Unsigned int providing a negative value?

11,011

Solution 1

Printing %d will read the integer as a signed decimal number, regardless of its defined type.

To print unsigned numbers, use %u.

This happens because of C's way to handle variable arguments. The compiler just pulls values from the stack (typed as void* and pointing to the call stack) and printf has to figure out what the data contains from the format string you give it to.

This is why you need to supply the format string - C has no way of RTTI or a 'base class' (Object in Java, for example) to get a generic or predefined toString from.

Solution 2

This should work:

unsigned int a;
printf("%u\n", a);

Explanation: On most architectures, signed integers are represented in two's complement. In this system, positive numbers less than 2**(N-1) (where N = sizeof(int)) are represented the same way regardless whether you are using an int or a unsigned int. However, if the number in your unsigned int is larger than 2**(N-1), it represents a negative signed number under two's complement -- which is what printf gave you when you passed it "%d".

Solution 3

%d means printf will interpret the value as an int(which is signed). use %u if it is an unsigned int.

Share:
11,011
Dannul
Author by

Dannul

Updated on June 04, 2022

Comments

  • Dannul
    Dannul almost 2 years

    I have an unsigned integer but when i print it out using %d there is sometimes a negative value there?

  • unwind
    unwind over 14 years
    Nitpick: C is call by value, so the compiler pulls argument values, not pointers. You don't pass pointers to values (printf("%u", &myvariable);), you pass values directly (printf("%u", myvariable);).
  • visual_learner
    visual_learner over 14 years
    @LiraNuna - The implementation of varargs functions isn't specified, which is why neither #define va_copy(dest, src) dest = src or #define va_copy(dest, src) memcpy(dest, src, sizeof(va_list)) is a portable replacement for the va_copy macro on systems where it isn't provided. One of them may work, but who knows which?
  • LiraNuna
    LiraNuna over 14 years
    Okay then, "most commonly implemented by ...". There isn't really another effective way to move an unknown amount of data where each of the arguments has a variable size... a pointer is a constant size and the compiler already has the size information from the caller. va_copy is an intrinsic aswell.
  • Admin
    Admin over 14 years
    LiraNuna: Sure there is, push it (in the sense of asm push instructions) to the stack. va_copy doesn't have to be an intrinsic, it does have to know implementation details which vary across implementations.
  • Admin
    Admin over 14 years
    Ah, I see that if you stretch "pass a pointer to the stack" to mean the register that indicates the current stack frame, you'd be right, but that's too much of a stretch.
  • LiraNuna
    LiraNuna over 14 years
    @Roger: Yes, push it - and then provide printf with the pointer to the the location of the argument on the stack - since the argument is of dynamic size. I don't get why you argue about something we agree. English is not my native language, so I'm sorry if there's misunderstanding.
  • Admin
    Admin over 14 years
    We don't agree. How many "pointers" do you think printf gets for printf(s, a, b, c)? Saying the stack is "provided by a pointer" is enough of a stretch to be considered plain wrong---at that point you're not writing C. (Certainly could be a language issue.)
  • Johannes Schaub - litb
    Johannes Schaub - litb over 14 years
    But this is how every function call behaves that doesn't use registers. It's not something specific to printf or vararg functions, actually. The stack frame of the current function starts somewhere, and there, or directly below it, will be the incoming arguments, on many architectures anyway.
  • Steve Jessop
    Steve Jessop over 14 years
    It's implementation-dependent whether there's a stack at all. Arguments just are. In practice (as LiraNuna says and everyone else very well knows) almost every calling convention you will ever encounter has a means of passing a stack pointer, even if it's by the CPU itself having a dedicated register only for that purpose. It's not necessarily the case that all arguments are passed on the stack - some calling conventions pass the first few in registers. However, it's a PITA implementing varargs with such a calling convention, so I would not blame anyone who puts all varargs on stack :-)
  • M.M
    M.M almost 5 years
    x64 ABI passes some printf arguments in registers, so any explanation involving the stack is somewhat bogus