Reputation: 1503
The book I am using to learn C says that if a binary operator (except =
, &&
and ||
) is used with one operand of floating point type (say, float
) and one operand of integer type (say, int
) then the integer value is converted to a floating point value, and that this floating point type will also be the type of the result of the operation.
I don't understand the bold part. Why should, e.g., the comparison operator <
return a float?
I tried
float a=2.0;
int b=1;
printf("%d\n",(b<a)*16777217);
and it prints 16777217 as I expected. The number 16777217 is not representable as a float on my system.
So I would think this shows that the type of (b<a)
is int, not float - if it were float then (b<a)*16777217
would be of type float as well, and its value would be nearby the value 16777217, and this nearby value would get printed.
More, if I try
float a=2.0;
int b=1;
printf("%f\n",(b<a)*16777217);
it prints 0.000000.
Am I getting something wrong, or is the claim in my book wrong?
Upvotes: 2
Views: 2094
Reputation: 80325
Your particular question is about the type of a < b
. In C, this expression has type int
. The C99 standard, 6.5.8:6, says:
Each of the operators < (less than), > (greater than), <= (less than or equal to), and >= (greater than or equal to) shall yield 1 if the specified relation is true and 0 if it is false. The result has type
int
.
Your general question is about recognizing the type of an expression in C. There is no easy way to do this with just an ordinary C99 compiler, but I offer two solutions below. One attempt you made was printf("%f\n",(b<a)*16777217);
. This does not work. This printf()
call invokes undefined behavior because you are passing an integer for the %f
format. This is not the right way to test the type of an expression in C.
Instead:
If you have a C11 compiler, use _Generic
, a newly introduced construct that evaluates to different values depending on the type of an expression.
If you have the static analysis and transformation framework for C programs Frama-C, declare a variable of type typeof(e)
in a program and use frama-c -print
to see what type this was resolved to.
Here is an example program that declares a variable X
with the same type as (b<a)*16777217
:
int main(){
float a=2.0;
int b=1;
typeof((b<a)*16777217) X = 0;
}
This program is normalized and re-printed by Frama-C with the command below:
$ frama-c t.c -print
[kernel] preprocessing with "gcc -C -E -I. t.c"
/* Generated by Frama-C */
int main(void)
{
int __retres;
float a;
int b;
int X; // <- THE EXPRESSION HAD TYPE int
a = (float)2.0;
b = 1;
X = 0;
__retres = 0;
return __retres;
}
There were other oddities in my original program that were normalized at the same time as typeof
: I forgot a return
statement in function main()
(as is legal in C99) so one was added. I was initializing the float
variable a
with the double
constant 2.0
so the conversion was made explicit. The transformed, normalized program is still equivalent to the original.
Upvotes: 5