0

On ubuntu server 11.10 for i386, sizeof(int) is 4, so I guess 4294967296 is the maximum number for int type, isn't it? But printf("%u\n",4294967296) output 0 with a warning :

warning: format '%u' expects argument of type 'unsigned int', but argument 2 has type 'long long unsigned int' [-Wformat]

Any suggestion ?

The version of gcc is (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1

爱国者
  • 4,298
  • 9
  • 47
  • 66

4 Answers4

9

4294967296 is exactly 2^32, which is 1 beyond the maximum supported by unsigned int (assuming 32-bit). So C treats that integer literal as if it were of the next integer type that can represent it (long long int). (I'm not sure why the warning complains that it's long long unsigned int).

You've therefore invoked undefined behaviour by providing a mismatch between your format specifier and the argument types (in practice, you're simply seeing modulo wrap-around).

Change your format specifier to "%llu\n".

Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
  • Sorry, `printf("%lu\n", 4294967296 )` gives a waring `warning: format '%lu' expects argument of type 'long unsigned int', but argument 2 has type 'long long int' [-Wformat]` and output 0 – 爱国者 Jan 25 '12 at 09:07
3

You can use the constants in limits.h to determine the maximum possible and minimum possible values for various types for your implementation. Try

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

and you'll find that the output is:

4294967295

But you are asking printf() to print 4294967296 which is beyond the maximum possible unsigned integer for your implementation.

The value of UINT_MAX makes sense since you have told us that sizeof (int) is 4. The maximum possible 4-byte integer or 32-bit integer is 111111111 111111111 111111111 111111111 when expressed in binary or FFFFFFFF when expressed in hexadecimal or 4294967295 when expressed in decimal.

You have got two ways to fix this code. A simple way is:

printf("%llu\n", 4294967296ull);

A more portable way to fix this by using the ISO C99 standard is:

printf("%" PRIu64 "\n", (uint64_t) 4294967296);

For the latter, you need to #include <inttypes.h>.

Susam Pal
  • 32,765
  • 12
  • 81
  • 103
1

The type of an unsuffixed integer literal such as 4294967296 depends on the value of the literal and the ranges of the predefined types for the implementation.

The type of a decimal constant is the first of:

  • int
  • long int
  • long long int

(Octal and hexadecimal literals can be of unsigned types; see section 6.4.4.1 of the C99 standard for details.)

in which its value can be represented exactly. The language requires that int is at least 16 bits, long int is at least 32 bits, and long long int is at least 64 bits, but each can be wider.

On your system (Ubuntu, 32 bits, same as mine), int and long int are both 32 bits, and long long int is 64 bits, so 4294967296 is of type long long int. (The message you showed us indicates that it's long long unsigned int, which doesn't seem right; are you sure that's the message you got for that specific code?)

The behavior of calling printf with an argument of a type that's inconsistent with the format is undefined. You probably got 9 as output because the value passed was 0x0000000100000000, and printf happened to use the low-order 32 bits of the 64-bit value. Other behaviors are possible.

You ask for "Any suggestion", but it's not clear from your question what you want to do. A way to produce the output you probably expected is:

puts("4294967296");

but I'm sure that's not the kind of answer you're looking for.

Usually when you print a number with printf, the argument will be a variable rather than a literal, and the type will be determined by the declared type of the variable. Or it might be a more complicated expression, in which case the type is determined by the types of the operands; if they're of different types, there's a moderately complicated set of rules that determine what the final result is. Just make sure the format you use corresponds to the (promoted) type of the argument.

If you have a more specific question, we'll be glad to give a more specific answer.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
0

If you want do do it in a portable way take a look at here.

Community
  • 1
  • 1
Ortwin Angermeier
  • 5,957
  • 2
  • 34
  • 34