Strange behaviour, bug in Borland compiler?

  • Thread starter Markus Sandheide
  • Start date
M

Markus Sandheide

Hello!

Execute these lines:

int x = 1;
x = x > 2345678901;

You will get:

x == 1 with Borland C++ Builder
x == 0 with Microsoft Visual Studio

"int" is 32 bit in both compilers.
So the result should be the same.
Is this a bug in the Borland compiler?

Greetings,
Markus Sandheide
 
I

Ioannis Vranos

Markus said:
Hello!

Execute these lines:

int x = 1;
x = x > 2345678901;

You will get:

x == 1 with Borland C++ Builder
x == 0 with Microsoft Visual Studio

"int" is 32 bit in both compilers.
So the result should be the same.
Is this a bug in the Borland compiler?



It looks like a missing in your C++ knowledge. Read an up to date ISO
C++ book.


You may check http://www.accu.org at the book reviews section.


Also take a look at a page of mine:

http://www23.brinkster.com/noicys/learningcpp.htm
 
K

Karl Heinz Buchegger

Markus said:
Hello!

Execute these lines:

int x = 1;
x = x > 2345678901;

You will get:

x == 1 with Borland C++ Builder
x == 0 with Microsoft Visual Studio

"int" is 32 bit in both compilers.
So the result should be the same.
Is this a bug in the Borland compiler?

Looks like a bug in Borland C++ Builder
 
C

Christian Gollwitzer

Markus said:
Hello!

Execute these lines:

int x = 1;
x = x > 2345678901;

2345678901 is not representable in a signed 32-bit int. Try with x=x>5, it
should give the correct result. Do you not get any warning when compiling this?

Christian
 
K

Karl Heinz Buchegger

Ioannis said:
It looks like a missing in your C++ knowledge.

Hmm. Then I am guilty too.
What am I missing? Could you enlighten me?

x is of type int with a value in its range
2345678901 is of type int with a value in its range (32 bit)
So there should be no problem in comparing those numbers.
 
C

Christian Gollwitzer

Karl said:
Hmm. Then I am guilty too.
What am I missing? Could you enlighten me?

x is of type int with a value in its range
2345678901 is of type int with a value in its range (32 bit)

int is *signed* int and is of the range -2147483648..2147483647 for 32bit.
2345678901 is therefore out of range, except for *unsigned* int.

Christian
 
U

Ulrich Achleitner

Hmm. Then I am guilty too.
What am I missing? Could you enlighten me?

x is of type int with a value in its range
2345678901 is of type int with a value in its range (32 bit)
So there should be no problem in comparing those numbers.

but the expression x > 2345678901 is of type bool, and its boolean result
is then converted to an int...
i do not think that there are any prescriptions in the standard saying
that false must be converted to 0
(however, it is bad style anyway to mess with types in such a way)
 
K

Karl Heinz Buchegger

Ulrich said:
but the expression x > 2345678901 is of type bool, and its boolean result
is then converted to an int...
i do not think that there are any prescriptions in the standard saying
that false must be converted to 0

There are
 
K

Karl Heinz Buchegger

Christian said:
int is *signed* int and is of the range -2147483648..2147483647 for 32bit.
2345678901 is therefore out of range, except for *unsigned* int.

Ah. Shit.
I just used my desktop calculator: 2^32 - 1
For signed int it needs to be: 2^31 - 1

Thanks
 
K

Karl Heinz Buchegger

Karl said:
There are

To elaborate:

4.5 Integral promotions

4 An rvalue of type bool can be converted to an rvalue of type int, with false
becoming zero and true becoming one

It turned out, that my math was simply wrong.
 
B

Bob Hairgrove

2345678901 is not representable in a signed 32-bit int. Try with x=x>5, it
should give the correct result. Do you not get any warning when compiling this?

Borland 5.5.1 doesn't warn about the above. However, change this to:

#include <iostream>
int main()
{
using namespace std;
int x=1;
unsigned int y = 2345678901;
x = x > y;
cout << x << endl;
}

and you get this:
Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
Warning W8012 10: Comparing signed and unsigned values in function
main()

Output is 0 when using a variable.
 
M

Mike Wahler

Re: Strange behaviour, bug in Borland compiler?

The behavior isn't 'strange', it's undefined.
Hello!

Execute these lines:

int x = 1;
x = x > 2345678901;

The value 2345678901 is outside the range of
a 32-bit signed int. You're not comparing 'x'
against 2345678901, but some unknown, undefined
value. You could get any result at all.
You will get:

x == 1 with Borland C++ Builder
x == 0 with Microsoft Visual Studio

Or possibly something else with another compiler, or
a different version of those compilers, or with the
same version of them, running the program again.
"int" is 32 bit in both compilers.
So the result should be the same.

The result is undefined.
Is this a bug in the Borland compiler?

No, the bug is in your code. The maximum possible
value for 32-bit signed int is 2147483647.

Try changing the type to unsigned int.

-Mike
 
O

Old Wolf

Christian said:
2345678901 is not representable in a signed 32-bit int.

But it is representable in an unsigned 32-bit int.
Try with x=x>5, it should give the correct result.

Are you trying to say that 1 is the correct result
for the original case?
Do you not get any warning when compiling this?
No diagnostic is required. (although it would be nice
if there were).
 
M

msandheide

No, the bug is in your code. The maximum possible
value for 32-bit signed int is 2147483647.

Then there is a bug in the Microsoft Foundation Classes C++ library:

Have a look at CByteArray::SetSize, you can find it here:
http://www.dpi.ufv.br/downloads/C++ Introductory Edition/VCB600ENU1/VC98/MFC/SRC/ARRAY_B.CPP

There is this line:
ASSERT(nNewSize <= SIZE_T_MAX/sizeof(BYTE));

nNewSize is an int and SIZE_T_MAX is UINT_MAX.

If you compile this code in debug mode with Borland the ASSERT fails
because of the differtent behaviour of Borland that I described.
Markus Sandheide
 
M

msandheide

No, the bug is in your code. The maximum possible
value for 32-bit signed int is 2147483647.

Then there is a bug in the Microsoft Foundation Classes C++ library:

Have a look at CByteArray::SetSize, you can find it here:
http://www.dpi.ufv.br/downloads/C++ Introductory Edition/VCB600ENU1/VC98/MFC/SRC/ARRAY_B.CPP

There is this line:
ASSERT(nNewSize <= SIZE_T_MAX/sizeof(BYTE));

nNewSize is an int and SIZE_T_MAX is UINT_MAX.

If you compile this code with Borland the ASSERT always fails because
of the different behaviour of Borland that I described.
Markus Sandheide
 
C

Christian Gollwitzer

Old said:
But it is representable in an unsigned 32-bit int.

OK, so if you understand it as an unsigned integer constant, you would have a
comparison between signed int x and unsigned int constant. I'd expect that this
gives undefined behaviour, though I don't have the standard to check against.
Are you trying to say that 1 is the correct result
for the original case?

?? I say, the line x= x>5 should produce x==0 in any case, because 1>5 is false.
It should not depend on the compiler. If it does, it is a compiler bug.
No diagnostic is required. (although it would be nice
if there were).

After completing the example:

#include <iostream>

int main() {
int x = 1;
x = x > 2345678901;
std::cout<<x<<std::endl;
return 0;
}

g++ -Wall gives me:

test.cpp: In function `int main()':
test.cpp:5: Warnung: this decimal constant is unsigned only in ISO C90
test.cpp:5: Warnung: comparison between signed and unsigned integer expressions

and marking the constant as unsigned "2345678901u"

test.cpp: In function `int main()':
test.cpp:5: Warnung: comparison between signed and unsigned integer expressions

so in any case, I get the "comparison between signed and unsigned" warning as
expected.

Christian
 
J

Jack Klein

Hello!

Execute these lines:

int x = 1;
x = x > 2345678901;

You will get:

x == 1 with Borland C++ Builder
x == 0 with Microsoft Visual Studio

"int" is 32 bit in both compilers.
So the result should be the same.
Is this a bug in the Borland compiler?

Greetings,
Markus Sandheide

Mike Whaler has it mostly right, and quite a few other people have it
wrong.

A decimal literal without a suffix indicating that it is unsigned
NEVER becomes an unsigned type in either C or C++.

In C++, the type of a decimal literal is int if its value is within
the range of signed int. It its value is outside the range of signed
int, it has type signed long if it is within the range of signed long.

2345678901 is greater than INT_MAX for a 32-bit 2's complement signed
int. But since both the compilers you use have 32-bit 2's complement
signed long, it also outside the range of values for signed long. So
the result is undefined behavior.

Note that if compiled and executed this program on a platform where
int has 32 bits and long has 64 bits, such as 64 bit Windows and
perhaps some others, then the literal would easily fit into a signed
long. In the comparison 'x' would get promoted to signed long and the
result would be false.

Since you are not using an implementation where signed int or signed
long has more than 32-bits, neither compiler is right or wrong as far
as the language is concerned. There is no right or wrong once you
produce undefined behavior.
 
R

Ron Natalie

Karl said:
Hmm. Then I am guilty too.
What am I missing? Could you enlighten me?

x is of type int with a value in its range
2345678901 is of type int with a value in its range (32 bit)
So there should be no problem in comparing those numbers.

That number is too big for a signed 32 bit int, so it's converted
to unsigned. The test should still work (1 gets promoted to unsigned
1).
 
O

Old Wolf

Christian said:
OK, so if you understand it as an unsigned integer constant,
you would have a comparison between signed int x and unsigned
int constant. I'd expect that this gives undefined behaviour

In fact the signed int is converted to unsigned and then they
are compared. The conversion works by modular arithmetic
(ie. you add or subtract TYPE_MAX+1 from the signed value until
it is in the range of the unsigned value). So the comparison
becomes 1U > 2345678901U .

Sorry , bad wording by me -- 0 is the correct result
It should not depend on the compiler.
If it does, it is a compiler bug.

There are some things in C where the result depends on the compiler
(although this case should not be one of them)
g++ -Wall gives me:

test.cpp: In function `int main()':
test.cpp:5: Warnung: this decimal constant is unsigned only in ISO
C90

Looking at the C99 draft, it appears as if 2345678901 is a
signed long long. (The result of 1LL > 2345678901LL is still 0).
test.cpp:5: Warnung: comparison between signed and unsigned integer
expressions
so in any case, I get the "comparison between signed and unsigned"
warning as expected.

Right. The Borland compiler doesn't give you the warning --
it's entitled to not do that. (Although it should give the
correct answer!) Have you tried with Borland 5.6.4 ?
 

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,743
Messages
2,569,478
Members
44,898
Latest member
BlairH7607

Latest Threads

Top