C中float与int比较的结果类型

lee*_*e77 2 c int comparison

我使用的学习C书中说,如果二元运算符(除=&&||)与浮点类型的一个操作数(比如说,使用float)和整数类型(比如,一个操作数int),那么整数值转换为浮点值,并且该浮点类型也将是运算结果的类型

我不理解大胆的部分。例如,比较运算符为什么要<返回浮点数?

我试过了

float a=2.0;
int b=1;
printf("%d\n",(b<a)*16777217);
Run Code Online (Sandbox Code Playgroud)

并按我的预期打印16777217。数字16777217在我的系统上不能表示为浮点数。

因此,我认为这表明(b<a)int 的类型是int,而不是(b<a)*16777217float- 如果它是float,则其类型也将是float,其值将在值16777217附近,并且此附近的值将被打印。

更多,如果我尝试

float a=2.0;
int b=1;
printf("%f\n",(b<a)*16777217);
Run Code Online (Sandbox Code Playgroud)

它打印0.000000。

我弄错了吗,还是书中的主张错了?

Pas*_*uoq 5

您的特定问题是关于的类型a < b。在C中,此表达式的类型为int。C99标准6.5.8:6表示:

如果指定的关系为true,则每个运算符<(小于),>(大于),<=(小于或等于)和> =(大于或等于)应产生1,如果为0,则产生0。假。结果具有类型int


您的一般问题是关于识别C语言中表达式的类型。仅使用普通的C99编译器没有简单的方法来实现此目的,但是我在下面提供了两种解决方案。您尝试过的一种尝试是printf("%f\n",(b<a)*16777217);。这是行不通的。该printf()调用调用未定义的行为,因为您正在为该%f格式传递整数。这不是在C中测试表达式类型的正确方法。

代替:

  • 如果您使用的是C11编译器,请使用_Generic,这是新引入的构造,根据表达式的类型计算得出不同的值。

  • 如果您具有C程序Frama-C的静态分析和转换框架,请在程序中声明一个type变量,typeof(e)然后使用它frama-c -print来查看将其解析为哪种类型。

这是一个示例程序,该程序声明X与以下类型相同的变量(b<a)*16777217

int main(){
  float a=2.0;
  int b=1;
  typeof((b<a)*16777217) X = 0;
}
Run Code Online (Sandbox Code Playgroud)

该程序已被Frama-C规范化并重新打印,使用以下命令:

$ 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;
}
Run Code Online (Sandbox Code Playgroud)

我的原始程序中还有其他奇怪之处,同时也进行了规范化typeof:我忘记了return函数中的一条语句main()(在C99中是合法的),因此添加了一条。我正在使用常量初始化float变量a,因此转换是明确的。转换后的标准化程序仍与原始程序等效。double2.0