cout << -2147483648 ; strange output in g++

S

suresh

Hi,

For this code snippet, I get the following output, which I am unable
to understand.
(2^31 = 2147483648)

cout<< -2147483648 << endl;
cout << numeric_limits<int>::min() <<',' <<
numeric_limits<int>::max()<< endl;

The outputs I get are:
2147483648
-2147483648,2147483647

with this compile time warning: this decimal constant is unsigned only
in ISO C90

I am surprised why the negative number is printed as positive.

Could you please explain why this behaviour?

thanks
suresh
 
V

Victor Bazarov

suresh said:
For this code snippet, I get the following output, which I am unable
to understand.
(2^31 = 2147483648)

cout<< -2147483648 << endl;
cout << numeric_limits<int>::min() <<',' <<
numeric_limits<int>::max()<< endl;

The outputs I get are:
2147483648
-2147483648,2147483647

with this compile time warning: this decimal constant is unsigned only
in ISO C90

I am surprised why the negative number is printed as positive.

Could you please explain why this behaviour?

The literal '2147483648' does not fit in an int, therefore it is
promoted to 'long int'. If your system's 'long' has the same size
as 'int' (like on Windows, for example), the behaviour is undefined.

Try adding the suffix 'U' to the literal.

V
 
J

Jim Langston

suresh said:
Hi,

For this code snippet, I get the following output, which I am unable
to understand.
(2^31 = 2147483648)

cout<< -2147483648 << endl;
cout << numeric_limits<int>::min() <<',' <<
numeric_limits<int>::max()<< endl;

The outputs I get are:
2147483648
-2147483648,2147483647

with this compile time warning: this decimal constant is unsigned only
in ISO C90

I am surprised why the negative number is printed as positive.

Could you please explain why this behaviour?

The range for a 32 bit signed number using 2's complement is -2147483647 to
2147483648. -2147483648 does not fit in a signed 32 bit int. On a 32 bit
compiler, a 32 bit number may be the largest. Since -2147483648 does not
fit in a signed 32 bit int, it seems it is converting it to an unsigned 32
bit int.

Basically, the number you are trying to represent doesn't fit in an int
variable. I believe this is giving you an undefined value.
 
R

Rolf Magnus

Victor said:
The literal '2147483648' does not fit in an int, therefore it is
promoted to 'long int'.

My compiler promoted it to unsigned long.
If your system's 'long' has the same size as 'int' (like on Windows, for
example), the behaviour is undefined.

Try adding the suffix 'U' to the literal.

How would that help? Or did you miss that the OP actually wanted to print a
negative int value?
 
S

suresh

HI Victor,

Could you be little bit more elaborative? The max value of int in my
linux machine is 2147483648. Then why did you say that The literal
'2147483648' does not fit in an int?

long has the same size as int on my machine too.

suresh
 
S

suresh

Hi Jim Langston,

As I understand, the range of 32 bit signed number is -2147483648 to
2147483647. So it should work correctly.

Again, the code snippet,

signed int x = -2147483648;
cout << x << endl;

works correctly though the warning "this decimal constant is unsigned
only in ISO C90" is produced.

suresh.
 
J

Jim Langston

suresh said:
Hi Jim Langston,

As I understand, the range of 32 bit signed number is -2147483648 to
2147483647. So it should work correctly.

Again, the code snippet,

signed int x = -2147483648;
cout << x << endl;

works correctly though the warning "this decimal constant is unsigned
only in ISO C90" is produced.

suresh.

Undefined. Undefined means it may work as expected, or not. Which is what
you're running into. Just because it gives you output you expect at one
point and not an other doesn't meat it's always going to work that way.

Trying to define undefined behavior is like trying to herd cats.
 
S

suresh

My question is different. An integer can really take the value
-2147483648. Then why undefined behaviour etc?

suresh
 
B

Bo Persson

suresh wrote:
:: Hi,
::
:: For this code snippet, I get the following output, which I am
:: unable to understand.
:: (2^31 = 2147483648)
::
:: cout<< -2147483648 << endl;
:: cout << numeric_limits<int>::min() <<',' <<
:: numeric_limits<int>::max()<< endl;
::
:: The outputs I get are:
:: 2147483648
:: -2147483648,2147483647
::
:: with this compile time warning: this decimal constant is unsigned
:: only in ISO C90
::
:: I am surprised why the negative number is printed as positive.
::
:: Could you please explain why this behaviour?
::

Your value -2147483648 actually has two parts, 2147483648 and a minus
sign. The problem is that 2147483648 is too large to fit in an int, so
you really need a larger type to store it. If you don't have that,
you're in trouble!

If you look in the limits.h header (or <climits>), I bet the value for
INT_MIN is written something like

#define INT_MIN (-2147483647 - 1)

to avoid this overflow.



Bo Persson
 
S

suresh

Hi Bo Persson,

Thanks for the wonderful answer. But then why did it work correctly in
this way?

int x = -2147483648;
cout << x << endl;
//why the two parts thing you said is not applying here?
suresh
 
P

Pavel Shved

Hi,

For this code snippet, I get the following output, which I am unable
to understand.
(2^31 = 2147483648)

šcout<< š-2147483648 << endl;
š cout << numeric_limits<int>::min() <<',' <<
numeric_limits<int>::max()<< endl;

The outputs I get are:
2147483648
-2147483648,2147483647

with this compile time warning: this decimal constant is unsigned only
in ISO C90

I am surprised why the negative number is printed as positive.

Could you please explain why this behaviour?

thanks
suresh

I'm not too invilved with this but i'll try to guess.

First lets parse compiler warning message. `only' refers to the
phrase before it, so we're guessing that in C90 standard that you're
obviously compiling against this constant can be unsigned only.

Second, how a constant with minus sign can be `unsigned only'? The
onyl reasonable explanation is that compiler interpretes it as
negation of positive constant. Remembering that positive constant is
`unsigned only', we deduce that compiler tries to do negation of an
unsigned type -- and having no hint assignes (willing to be negative)
result to an unsigned value. Lets try to see how the code is
interpreted:

unsigned int c=2147483648; //in times of C90 noone knew about long
long int`s.
c=-c;
cout << c;

. This yields quite obvious result of 2147483648.


That's a Sherlock-Holmes-like work of sort, so its all imho. Sorry
for a second unreliable post today.
 
P

Pavel Shved

int x = š-2147483648;
cout << x << endl;
//why the two parts thing you said is not applying here?
suresh

Because you've explicitely specified the type of x. In the OP
compiler has to guess the type of `2147483648' (not the same with `-'
sign) by his own and he eventually deduces it's unsigned - according
to C90 standard.
 
S

suresh

Hi Pavel Shved,

Wow. thanks. but can you elaborate just the part quoted below? It is
not clear to me.
suresh
 
P

Pavel Shved

Hi Pavel Shved,

Wow. thanks.

Nothing to thank for, really. My 2nd post is utter nonsence (it
states that float x=1/3; will not set x to 0.0).
but can you elaborate just the part quoted below? It is
not clear to me.

elaboration is up to you. I'm doing guessing only: i have no compiler
near me. The same thing as guessing is done by compiler. My code
merely shows what your code turns into if compiler's guessing rules
are same as Bo Presson described. Maybe - MAYBE - compiler's guessing
rules depend on whether you specify the type in this particular case
(your latest example). Maybe not.

But amongst these maybies there is one sure-thing. Do not let
compiler guess your types! Use Bo Persson's solution and even add
suffixes to ints there :)
 
M

Mike Smith

Jim said:
Undefined.

I must admit that I, too, don't see why this is undefined. The range
for a 2's complement 32-bit signed int is -2147483648 to +2147483647.

0111 1111 1111 1111 = +2147483647
1000 0000 0000 0000 = -2147483648

So why should "cout << -2147483648 << endl" fail to print correctly?

FWIW, for "cout << -2147483648 << endl" I get "2147483648" as output,
but for "cout << (-2147483647 - 1) << endl" I get "-2147483648"...
 
R

Rolf Magnus

Mike said:
I must admit that I, too, don't see why this is undefined. The range
for a 2's complement 32-bit signed int is -2147483648 to +2147483647.

Yes, but the '-' is not part of the integer literal. It's an operator that
is applied to it. Now the C++ standard says:

"The type of an integer literal depends on its form, value, and suffix. If
it is decimal and has no suffix, it has the first of these types in which
its value can be represented: int, long int; if the value cannot be repre-
sented as a long int, the behavior is undefined."

Since 2147483648 is too big for int or long int, you get undefined behavior.
So why should "cout << -2147483648 << endl" fail to print correctly?

FWIW, for "cout << -2147483648 << endl" I get "2147483648" as output,
but for "cout << (-2147483647 - 1) << endl" I get "-2147483648"...

In this case, it's correct, because 2147483647 can be represented as a value
of type int.
 
B

Bo Persson

suresh wrote:
:: Hi Bo Persson,
::
:: Thanks for the wonderful answer. But then why did it work
:: correctly in this way?
::
:: int x = -2147483648;
:: cout << x << endl;
:: //why the two parts thing you said is not applying here?

They are. :)

Either you have some type wider than int, like long on some compilers.
If so, you get a negative long value and convert that to an int.

Or, you don't. In that case you have the dreaded Undefined behaviour,
meaning that anything can happen. One of the things that can happen is
that it just *seems* to work (sometimes).


Bo Persson



:: suresh
::
::
::: Your value -2147483648 actually has two parts, 2147483648 and a
::: minus sign. The problem is that 2147483648 is too large to fit in
::: an int, so you really need a larger type to store it. If you
::: don't have that, you're in trouble!
:::
::: If you look in the limits.h header (or <climits>), I bet the
::: value for INT_MIN is written something like
:::
::: #define INT_MIN (-2147483647 - 1)
:::
::: to avoid this overflow.
:::
::: Bo Persson
 
V

Victor Bazarov

Rolf said:
My compiler promoted it to unsigned long.

That's against the Standard. See [lex.icon]/2.
How would that help? Or did you miss that the OP actually wanted to
print a negative int value?

At least it would get rid of undefinedness.

V
 

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

Members online

Forum statistics

Threads
473,769
Messages
2,569,578
Members
45,052
Latest member
LucyCarper

Latest Threads

Top