Bug in GCC?

B

boltar2003

hi

Can someone tell me whats going on here. I'm using gcc 4.3.3 in linux.
Have I missed something obvious in the code snippet below or is there some
odd casting bug going on with gcc?

$ cat t.c
#include <stdio.h>

main()
{
double d = -2.345;
printf("%f\n",(double)(1 ? (int)d : (unsigned int)1));
}
$ cc t.c
$ ./a.out
4294967294.000000

If you change unsigned int to unsigned char then you get -2 as expected as
the result.

B2003
 
P

Pramod Subramanyan

The type of (1 ? (int)d : (unsigned int)1) is unsigned int. So d is
being cast to (int) -2, which in turn is cast to (unsigned)
4294967294. Your final cast takes it from (unsigned) 4294967294 to
(double) 4294967294.

--pramod
 
W

William Hughes

hi

Can someone tell me whats going on here. I'm using gcc 4.3.3 in linux.
Have I missed something obvious in the code snippet below or is there some
odd casting bug going on with gcc?

$ cat t.c
#include <stdio.h>

main()
{
        double d = -2.345;
        printf("%f\n",(double)(1 ? (int)d : (unsigned int)1));}

$ cc t.c
$ ./a.out
4294967294.000000

If you change unsigned int to unsigned char then you get -2 as expected as
the result.

B2003

The point is that the type of x?y:z depends on the types
of both y *and* z. The fact that z is not evaluated does not
matter. If y is int and z is of unsigned int, x?y:z is of unsigned
int, if y is int and z is unsigned char, x?y:z is type int.
(double)((unsigned int)((int) d)) = 4294967294.000000

- William Hughes
 
E

Eric Sosman

hi

Can someone tell me whats going on here. I'm using gcc 4.3.3 in linux.
Have I missed something obvious in the code snippet below or is there some
odd casting bug going on with gcc?

$ cat t.c
#include<stdio.h>

main()
{
double d = -2.345;
printf("%f\n",(double)(1 ? (int)d : (unsigned int)1));
}
$ cc t.c
$ ./a.out
4294967294.000000

Right. (Well, it depends on the value of UINT_MAX, but on
most 32-bit systems this is what you should expect.)
If you change unsigned int to unsigned char then you get -2 as expected as
the result.

Right again.

Remember, every expression in C has a single type, fixed at
compile time and immutable thereafter. In particular, the type
of `x?y:z' is one type, not "sometimes the type of y and sometimes
the type of z, depending on x." So, what happens when y and z
start out as different types? The same thing that happens when
you compute `y+z' or `y>z' or pretty much anything else: The "usual
arithmetic conversions" are performed, and the result has the type
that those conversions produce. So, what's the type of `-2 + 1u'?
And what's the type of `1 ? -2 : 1u'?

By the way, if you crank up gcc's warning levels it will tell
you "warning: signed and unsigned type in conditional expression."
I think it's good practice to crank up the warnings as high as your
code can stand -- and even if you don't routinely put them to the
max, you should *definitely* do so when confronted with a mystery.
 
B

boltar2003

Right again.

Remember, every expression in C has a single type, fixed at
compile time and immutable thereafter. In particular, the type

Ah ok. That never occured to me. I always just treated the question
mark operator as a version of "if".

Thanks for everyones help.
By the way, if you crank up gcc's warning levels it will tell
you "warning: signed and unsigned type in conditional expression."
I think it's good practice to crank up the warnings as high as your
code can stand -- and even if you don't routinely put them to the
max, you should *definitely* do so when confronted with a mystery.

Good idea.

B2003
 
L

lawrence.jones

Can someone tell me whats going on here. I'm using gcc 4.3.3 in linux.
Have I missed something obvious in the code snippet below or is there some
odd casting bug going on with gcc? [...]
printf("%f\n",(double)(1 ? (int)d : (unsigned int)1));

Neither. What's happening is that the value of d is converted to an int
(-2), but then that value is converted to unsigned int (because the
result of the ?: operator has the type that results from applying the
usual arithmetic conversions to the second and third operands), which
turns the small negative value into a large unsigned value, which is
then converted to double.
 
R

Richard Bos

double d = -2.345;
printf("%f\n",(double)(1 ? (int)d : (unsigned int)1));

What you want (if you want something like this at all, which I doubt) is

printf("%f\n", 1 ? (double)(int)d : (double)(unsigned int)1 );

That way, each half is first cast to its desired type, and then
_immediately_ to double, without going through another conversion
required by the use of ?:. The type of the entire ?: operation will then
be double, of course.

More interesting than a correct way to do something iffy, though, is the
question why you would want to do something this iffy in the first
place. It doesn't seem like a natural thing to do, to me. What are your
_actual_ requirements, and why can't you just do

printf("%f\n", (double) (1? (int)d :1) );

Richard
 
B

bart.c

Eric Sosman said:
On 5/12/2010 10:08 AM, (e-mail address removed) wrote:
Remember, every expression in C has a single type, fixed at
compile time and immutable thereafter. In particular, the type
of `x?y:z' is one type, not "sometimes the type of y and sometimes
the type of z, depending on x." So, what happens when y and z
start out as different types? The same thing that happens when
you compute `y+z' or `y>z' or pretty much anything else: The "usual
arithmetic conversions" are performed, and the result has the type
that those conversions produce. So, what's the type of `-2 + 1u'?
And what's the type of `1 ? -2 : 1u'?

Interesting. What's the type of the ?: expression in these two examples:

int a,b,c,d;
float x,y;

d=(c?a:x =b);
y=(c?a:x =b);

(This works as expected in my gcc.)
 
E

Eric Sosman

[...] The same thing that happens when
you compute `y+z' or `y>z' or pretty much anything else: The "usual
arithmetic conversions" are performed, and the result has the type
that those conversions produce. So, what's the type of `-2 + 1u'?
And what's the type of `1 ? -2 : 1u'?

Interesting. What's the type of the ?: expression in these two examples:

int a,b,c,d;
float x,y;

d=(c?a:x =b);
y=(c?a:x =b);

I see no expressions here at all, just constraint violations
the compiler is required to complain about.

What are you really asking?
 
B

bart.c

Eric Sosman said:
[...] The same thing that happens when
you compute `y+z' or `y>z' or pretty much anything else: The "usual
arithmetic conversions" are performed, and the result has the type
that those conversions produce. So, what's the type of `-2 + 1u'?
And what's the type of `1 ? -2 : 1u'?

Interesting. What's the type of the ?: expression in these two examples:

int a,b,c,d;
float x,y;

d=(c?a:x =b);
y=(c?a:x =b);

I see no expressions here at all, just constraint violations
the compiler is required to complain about.

Just pointing out that ?: expressions involving lvalues might have different
rules (for determining the common type). Here's a more practical example:

int a=0,b,c=1;
char ch;

b = ++(c?ch:a);

(This is non-standard, nevertheless someone has implemented it, and must
have discovered that treating ?: as you describe wouldn't have worked.)
 
E

Eric Sosman

Eric Sosman said:
[...] The same thing that happens when
you compute `y+z' or `y>z' or pretty much anything else: The "usual
arithmetic conversions" are performed, and the result has the type
that those conversions produce. So, what's the type of `-2 + 1u'?
And what's the type of `1 ? -2 : 1u'?

Interesting. What's the type of the ?: expression in these two examples:

int a,b,c,d;
float x,y;

d=(c?a:x =b);
y=(c?a:x =b);

I see no expressions here at all, just constraint violations
the compiler is required to complain about.

Just pointing out that ?: expressions involving lvalues might have
different rules (for determining the common type).

They do not. If you think you've pointed out a difference,
you think wrongly.
Here's a more
practical example:

int a=0,b,c=1;
char ch;

b = ++(c?ch:a);

(This is non-standard, nevertheless someone has implemented it, and must
have discovered that treating ?: as you describe wouldn't have worked.)

As you point out, your example is not C. This being comp.lang.c
and not comp.lang.plxlii, I wrote about the rules for determining the
types of C expressions. In fact, my text started "Remember, every
expression *in C* [emphasis added] has a single type..."
 

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

Similar Threads

Bug in gcc? 5
preprocessor bug? 2
bug in gcc? 17
Legal C or bug in gcc 31
A basic (?) problem with addresses (gcc) 44
Command Line Arguments 0
Fibonacci 0
Compiler bug in lcc-win32 31

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top