Integer overflow in expression

V

Vivek Mohan

Hi,
I am using gcc, and I am a bit confused about the warning message I
got when I compiled and ran this small code snippet -

int main() {
unsigned long x = 3*1024*1024*1024; /* 3GB */
printf(" %x ", x);
}

I got the following error,

In function `main':
:4: warning: integer overflow in expression

but when I use this

int main() {
unsigned long x = 0xC0000000; /* 3GB */
printf(" %x ", x);
}

It doesn't give out any errors. Any idea as to why its warning about
integer overflow when it is well within the range of 32bits ? My gcc
-v

Configured with: FreeBSD/i386 system compiler
Thread model: posix
gcc version 3.3.3 [FreeBSD] 20031106

Vivek
 
M

Malcolm

Vivek Mohan said:
unsigned long x = 3*1024*1024*1024; /* 3GB error*/
unsigned long x = 0xC0000000; /* 3GB OK*/
The compiler treats raw decimal integers as signed ints by default.If you
tag an "lu" on the end it will be OK.
 
R

Russell Hanneken

Vivek said:
I am using gcc, and I am a bit confused about the warning message I
got when I compiled and ran this small code snippet -

int main() {
unsigned long x = 3*1024*1024*1024; /* 3GB */
printf(" %x ", x);
}

I got the following error,

In function `main':
:4: warning: integer overflow in expression

The compiler considers the constants 3 and 1024 to be of type int. So
the result of the multiplication expression (3*1024*1024*1024) is also
int. But the result is too large to be represented as an int, so the
compiler complains of integer overflow.

You need to arrange things so that the result of the expression is an
unsigned long. Simply assigning the result to an unsigned long variable
won't do it. You should force the compiler to treat each operand in the
expression as an unsigned long, like this:

unsigned long x = 3ul * 1024ul * 1024ul * 1024ul;

Two other things: you forget to #include <stdio.h> (for printf), and the
conversion specifier in the printf statement should be %lx, not %x,
because x is an unsigned long.
but when I use this

int main() {
unsigned long x = 0xC0000000; /* 3GB */
printf(" %x ", x);
}

It doesn't give out any errors.

The compiler sees that the constant 0xC0000000 can't be represented as
an int, so it regards it as some other type--maybe unsigned long.
 
W

Wolfie

Vivek said:
Hi,
I am using gcc, and I am a bit confused about the warning message I
got when I compiled and ran this small code snippet -

int main() {
unsigned long x = 3*1024*1024*1024; /* 3GB */
printf(" %x ", x);
}

I got the following error,

In function `main':
:4: warning: integer overflow in expression

"3" and "1024" are both integers so you're calculating using integer
math. Specify one/both as a long constant.
 
J

Juergen Heinzl

Hi,
I am using gcc, and I am a bit confused about the warning message I
got when I compiled and ran this small code snippet -

int main() {
unsigned long x = 3*1024*1024*1024; /* 3GB */
printf(" %x ", x);
}

I got the following error,

In function `main':
:4: warning: integer overflow in expression
[-]
3 (signed) * 1024 (signed) * 1024 (signed) * 1024 (signed)
[-]
but when I use this

int main() {
unsigned long x = 0xC0000000; /* 3GB */
printf(" %x ", x);
}
[-]
Or this ...
3 * 1024 * 1024 * 1024u
.... or this ...
3u * 1024 * 1024 * 1024
.... or ...
It doesn't give out any errors.
[-]

Cheers,
Juergen
 
E

Eric Sosman

Vivek said:
Hi,
I am using gcc, and I am a bit confused about the warning message I
got when I compiled and ran this small code snippet -

int main() {
unsigned long x = 3*1024*1024*1024; /* 3GB */
printf(" %x ", x);
}

I got the following error,

In function `main':
:4: warning: integer overflow in expression

`3' is a signed int, and so are all three appearances
of `1024'. You have asked for these four signed ints to
be multiplied together, producing a product that is also
a signed int, and then for that signed int product to be
converted to unsigned long. The compiler is telling you
that the product is too large to fit in a signed int.

Here's a fix:

unsigned long x = 3u * 1024u * 1024u * 1024u;

Now all the operands are unsigned ints, and the product
is also an unsigned int. The product will not overflow a
32-bit unsigned int, so all will be well.

... maybe. It appears that your compiler uses 32 bits
for an int, but not all compilers do so. The C language
guarantees that an int has at least 16 bits, but does not
require it to be wider. If int (and hence unsigned int)
are 16 bits wide (or 18, or 24, or anything less than 32),
the product will not be "3GB" as you expect.

Here's a better fix:

unsigned long x = 3ul * 1024ul * 1024ul * 1024ul;

This time, all the operands are unsigned longs. In all C
implementations, long and unsigned long are at least 32
bits wide, possibly wider. That means that your calculation
will now behave as you intended, regardless of the platform.

By the way, you should use "%lx" rather than just "%x"
to print the value; the 'l' tells printf() that the operand
is "long" instead of "plain." You mention that you're using
gcc; if you run it as "gcc -Wall -W" it will catch this error
for you. (In my own work, I also add "-ansi -pedantic" for
all modules that can tolerate it; some system-dependent
modules cannot.)
 
M

Martin Ambuhl

Vivek said:
Hi,
I am using gcc, and I am a bit confused about the warning message I
got when I compiled and ran this small code snippet -

int main() {
unsigned long x = 3*1024*1024*1024; /* 3GB */
printf(" %x ", x);
}

I got the following error,

You should get more.
In function `main':
:4: warning: integer overflow in expression

The expression on the right of the equal sign has no longs (not to
mention unsigned longs), so is computed as an int. Try this fixed
version of your code:

#include <stdio.h> /* mha: fixed omitted header, providing
prototype required for variatic
function printf */
int main()
{
unsigned long x = 3ul * 1024 * 1024 * 1024; /* mha: fixed
initializer */
printf(" %lx\n", x); /* mha: fixed wrong specifier; fixed
implementation-specic behavior for
last output line not terminated with
an end-of-line character */
return 0; /* mha: added for the almost 100% of
people with C89, not C99 compilers */
}
 
R

Richard Bos

You need to arrange things so that the result of the expression is an
unsigned long. Simply assigning the result to an unsigned long variable
won't do it.

The reason for this, BTW, is that by the time the assignment is done,
the computation has already been performed using ints.
You should force the compiler to treat each operand in the
expression as an unsigned long, like this:

unsigned long x = 3ul * 1024ul * 1024ul * 1024ul;

No need. All you need is to force it to consider the first operand to be
an unsigned long; automatic promotions will ensure that the rest will be
promoted before being multiplied.

Richard
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Staff online

Members online

Forum statistics

Threads
473,992
Messages
2,570,220
Members
46,805
Latest member
ClydeHeld1

Latest Threads

Top