我使用的学习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。
我弄错了吗,还是书中的主张错了?
您的特定问题是关于的类型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