【发布时间】:2011-01-24 19:44:02
【问题描述】:
考虑这个程序
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;
}
有人能解释一下为什么从 double/float 到 int 的转换在第一种情况下可以正常工作,而在 printf 中则不能正常工作吗?
该程序是在 32 位 linux 机器上的 gcc-4.1.2 上编译的。
编辑: Zach's answer 似乎合乎逻辑,即使用格式说明符来确定要从堆栈中弹出什么。但是,请考虑以下后续问题:
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;
}
这是如何工作的?
【问题讨论】:
-
我也有类似的疑问。看到这个线程:stackoverflow.com/questions/2377733/how-does-this-program-work
-
char 是单个字符 - 它只是一个 8 位整数。当您对小于 int 的整数类型执行任何类型的操作时,它们将被提升为整数。这包括调用函数时。所以实际上它不是随机的机会导致你的 printf 调用工作,这种行为是定义的。实际上,在大多数 C ABI 中,您总是为堆栈上传递的每个变量分配至少一个机器字。
-
@SurajJain 是的,
<stdarg>参数传递只考虑根据默认参数提升(C11 §6.5.2.2/6,§7.16.1.1/2)提升的类型,这确实保证了char和int兼容。但是,这与用于算术的提升并不完全相同。此外,根据 ABI 来推理语言是危险的。确认没问题确实需要检查规则。 -
@Potatoswatter 我的评论是怎么被删除的?
-
@SurajJain 很奇怪。这个网站有很多版主,有时事情会随机消失。
标签: c