为什么sizeof响应与%f不同?

时间:2013-10-12 15:21:54

标签: c gcc escaping sizeof

为什么我的%d而不是%f的价值与我相同?

void main()
{ 
   int arr;
   printf("%f",sizeof(arr));
}

输出:2.168831

void main()
{ 
   int arr;
   printf("%d",sizeof(arr));
}

输出:4

3 个答案:

答案 0 :(得分:4)

为了给出更多解释,这是因为printf()是一个可变函数,并且在函数运行之前,参数的类型是未知的,并且从格式字符串中确定它们是什么。这意味着不会发生正常的隐式转换。

例如,如果您执行以下操作:

void myfunc(double d) {
    /*  Do something with d  */
}

int main(void) {
    int n = 5;
    myfunc(n);
    return 0;
}

然后编译器知道myfunc()接受double类型的参数,因此在传递之前可以并且将隐式地将nint转换为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_tprintf("%f",...告诉printf下一个参数的类型为doublesize_t在内存中的布局与double不同,因此printf错误地解释了此参数。

正如Grijesh指出的那样,正确使用的格式说明符是%zu,但如果你真的想使用%f

printf("%f",(double)sizeof(arr));

会起作用

答案 2 :(得分:3)

sizeof运算符返回`size_t您应该将%zu格式说明符与printf()

一起使用

请注意,size_tunsignedsigned尺寸可由ssize_t表示。

这两种类型都在stddef.h标题

中定义

§7.21.6.1C11标准的第9页表示

  

如果转换规范无效,则行为未定义。如果有任何论据   不是相应转换规范的正确类型,行为是   未定义。