lee77
lee77

Reputation: 1503

Type of the result of a comparison of float with int in C

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

Answers (1)

Pascal Cuoq
Pascal Cuoq

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

Related Questions