考虑这个计划
int main()
{
float f = 11.22;
double d = 44.55;
int i,j;
i = f; //cast float to int
j = d; //cast double to int
printf("i = %d, j = %d, f = %d, d = %d", i,j,f,d);
//This prints the following:
// i = 11, j = 44, f = -536870912, d = 1076261027
return 0;
}
Run Code Online (Sandbox Code Playgroud)
有人可以解释为什么从double/float到int的转换在第一种情况下正常工作,并且在printf中完成时不起作用?
该程序是在32位linux机器上的gcc-4.1.2上编译的.
编辑: Zach的答案似乎是合乎逻辑的,即使用格式说明符来确定从堆栈弹出的内容.但是请考虑这个后续问题:
int main()
{
char c = 'd'; // sizeof c is 1, however sizeof character literal
// 'd' is equal to sizeof(int) in ANSI C
printf("lit = %c, lit = %d , c = %c, c = %d", 'd', 'd', c, c);
//this prints: lit = d, lit = 100 , c = d, c = 100
//how does printf here pop off the right number of bytes even when
//the size represented by format specifiers doesn't actually match
//the size of the passed arguments(char(1 byte) & char_literal(4 bytes))
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这是如何运作的?
Zac*_*sch 19
该printf函数使用格式说明符来确定从堆栈弹出的内容.因此,当它看到时%d,它弹出4个字节并将它们解释为a int,这是错误的(二进制表示(float)3.0不同(int)3).
您需要使用%f格式说明符或将参数转换为int.如果您使用的是足够新的版本gcc,则启用更强的警告可以捕获此类错误:
$ gcc -Wall -Werror test.c
cc1: warnings being treated as errors
test.c: In function ‘main’:
test.c:10: error: implicit declaration of function ‘printf’
test.c:10: error: incompatible implicit declaration of built-in function ‘printf’
test.c:10: error: format ‘%d’ expects type ‘int’, but argument 4 has type ‘double’
test.c:10: error: format ‘%d’ expects type ‘int’, but argument 5 has type ‘double’
Run Code Online (Sandbox Code Playgroud)
回答问题的编辑部分:
C的整数提升规则表示,当作为vararg传递时,所有小于intget的类型都会被提升int.所以在你的情况下,'d'正在升级为a int,然后printf弹出int并转换为a char.我可以找到这种行为的最佳参考是这篇博客文章.
没有" int投入printf" 这样的东西.printf不做也不能做任何铸造.格式说明符不一致会导致未定义的行为.
实际上,printf只需接收原始数据并将其重新解释为格式说明符隐含的类型.如果你传递一个double值并指定一个int格式说明符(如%d),printf将取该double值并盲目地将其重新解释为a int.结果将是完全不可预测的(这就是为什么这样做正式导致C中的未定义行为).