为什么我的%d
而不是%f
的价值与我相同?
void main()
{
int arr;
printf("%f",sizeof(arr));
}
输出:2.168831
void main()
{
int arr;
printf("%d",sizeof(arr));
}
输出:4
答案 0 :(得分:4)
为了给出更多解释,这是因为printf()
是一个可变函数,并且在函数运行之前,参数的类型是未知的,并且从格式字符串中确定它们是什么。这意味着不会发生正常的隐式转换。
例如,如果您执行以下操作:
void myfunc(double d) {
/* Do something with d */
}
int main(void) {
int n = 5;
myfunc(n);
return 0;
}
然后编译器知道myfunc()
接受double
类型的参数,因此在传递之前可以并且将隐式地将n
从int
转换为double
参数。
当你这样做时:
int main(void) {
double f = 5.5;
printf("%d\n", f); /* WARNING: buggy code */
return 0;
}
编译器在运行之前不知道printf()
期望什么类型,并且理解格式字符串中的%d
。因此,它所能做的就是将double
参数作为double
传递,当printf()
运行并看到%d
时,它会将其解释为{{1}当错误解释位模式时(并且,在这种情况下,可能是参数的大小,以及在其之后的任何其他参数中抛弃它),事情将开始变得非常错误。
除其他外,这是为什么这些函数是在C中实际需要转换为int
的罕见情况之一的原因,因为指向不同类型对象的指针允许不同的大小,并且由于void *
需要%p
,因此您必须将void *
传递给它,而不是指向任何其他对象类型的指针。
请注意,现代编译器可以很聪明,并且他们知道标准C函数的工作原理,因此他们可以了解void *
等函数的标准行为,以便他们可以为您提供有关不匹配的警告像这样的参数类型,虽然它们实际上不会为你修复它们。
答案 1 :(得分:3)
sizeof
返回size_t
但printf("%f",...
告诉printf
下一个参数的类型为double
。 size_t
在内存中的布局与double
不同,因此printf
错误地解释了此参数。
正如Grijesh指出的那样,正确使用的格式说明符是%zu
,但如果你真的想使用%f
printf("%f",(double)sizeof(arr));
会起作用
答案 2 :(得分:3)
sizeof
运算符返回`size_t
您应该将%zu
格式说明符与printf()
请注意,size_t
为unsigned
,signed
尺寸可由ssize_t
表示。
这两种类型都在stddef.h
标题
§7.21.6.1C11标准的第9页表示
如果转换规范无效,则行为未定义。如果有任何论据 不是相应转换规范的正确类型,行为是 未定义。