8

2 Questions

First, while

long long int num = 1000000000000;

works fine

long long int num = 4014109449;

gives

warning: this decimal constant is unsigned only in ISO C90 [enabled by default]

What does it mean ?

Secondly

long long int num = 1000000*1000000;

gives an overflow warning while

long long int num = 1000000000000;

is ok,even though they are same.How do i get rid of it? Multiplication gives a garbage value

rohan013
  • 199
  • 1
  • 1
  • 14
  • 2
    You'll need to know the types of integer literals. See http://stackoverflow.com/q/8108642/420683 – dyp Nov 06 '13 at 18:05

2 Answers2

11

The problem is that the value 4014109449 is an unsigned long int in C90 but a long long int in C99 because it is too large for a 32-bit long int. While 1000000000000 is too large for any 32-bit type, so is automatically a long long int. The warning relates to the fact that the behaviour differs between C90 and C99.

The solution is to force type agreement between the literal and the variable type by using an appropriate type suffix. In this case:

long long num = 4014109449LL ;

or use a type cast:

long long num = (long long)4014109449 ;

Similarly the expression 1000000 * 1000000 is a multiply of two int types and has an int result, but causes an overflow - there is no automatic promotion to a larger type for int expressions. The solution is again to be explicit about the type of the literal:

long long num = 1000000LL * 1000000LL;

or you can also use a type cast on one or both operands.

long long num = (long long)1000000 * 1000000;
Clifford
  • 88,407
  • 13
  • 85
  • 165
  • But doesn't the compiler automatically promote the data type after multiplication ? – rohan013 Nov 06 '13 at 18:19
  • 1
    @rohan013, not for `int` types - that is the preferred data type for all operations. The automatic type promotion rules are somewhat arcane, it is always better to have explicit type agreement. Only one operand needs to be the larger type however to coerce the result to be of the larger type. – Clifford Nov 06 '13 at 18:23
  • No, the warning means "this decimal constant is unsigned *(only in ISO C90)*". In C99 and C11, all unsuffixed decimal constants are of signed types. See [my answer](http://stackoverflow.com/a/19820071/827263) for details. In C90, assuming 32-bit `long`, `1000000000000` is of type `unsigned long` (the warning could be clearer about that; it uses "unsigned" as an adjective, not as a type name). – Keith Thompson Nov 06 '13 at 18:38
  • @KeithThompson: `1000000000000` requires at least 40 bits, so cannot be `unsigned long`. rohan013 says the warning is for `4014109449`, so I am unclear what you are trying to explain. However your answer *is* clear. – Clifford Nov 06 '13 at 19:57
  • The `1000000000000` in my previous comment was a copy-and-paste error; I meant to say that `4014109449` is of type `unsigned long`. – Keith Thompson Nov 06 '13 at 20:02
  • @KeithThompson: Thanks, I have edited my answer in the light of your explanation, which I am feeling slightly bad about since mine was accepted (rather too fast perhaps), however the "solution" still worked even if the reasoning was flawed. Upvoting yours right now. – Clifford Nov 06 '13 at 20:06
4

In C90, the type of an unsuffixed decimal integer constant (literal) is the first of

  • int
  • long int
  • unsigned long int

that can represent its value without overflow.

In C99 and later, it's the first of

  • int
  • long int
  • long long int

that can represent its value.

The value 4014109449 happens to be representable as a 32-bit unsigned integer, but not as a 32-bit signed integer. Assuming your system has 32-bit longs, that constant's type is unsigned long int in C90, long long int in C99 and C11.

That's what the warning is telling you. The type of the constant changes depending on which version of the C standard your compiler conforms to.

Note that, regardless of its type, the value of 4014109449 will always be correct, and in your declaration:

long long int num = 1000000000000;

that value will always be correctly converted to long long. But it certainly wouldn't hurt (and would silence the warning) to add a LL suffix to make it explicit that you want a value of type long long:

long long int num = 1000000000000LL;

As for this:

long long int num = 1000000*1000000;

assuming you have 32-bit ints, the constant 1000000 is of type int, and the result of multiplying two int values is also of type int. In this case, the multiplication will overflow. Again, you can avoid the problem by ensuring that the constants are of type long long int:

long long int num = 1000000LL * 1000000LL;

(Note that you can use lowercase ll, but it's a bad idea, since it can be difficult to distinguish the letter l from the digit 1.)

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