1

为什么我没有得到与使用%d而不是使用相同的价值%f

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

输出: 2.168831

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

输出:4

4

3 回答 3

4

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

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

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

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

然后编译器知道它myfunc()接受一个类型的参数double,因此可以并且将在传递参数之前隐式转换为nintdouble

当你这样做时:

int main(void) {
    double f = 5.5;
    printf("%d\n", f);  /*  WARNING: buggy code  */
    return 0;
}

编译器在printf()运行并理解%d格式字符串中的 之前不知道期望什么类型。因此,它所能做的就是将double参数作为 a传递double,当printf()运行并看到时%d,它会将其解释int为论点,以及,把它扔给它之后的任何其他论点)。

这就是为什么这些函数是 C 中实际需要强制转换的少数情况之一的原因void *,因为指向不同类型对象的指针允许具有不同的大小,并且由于%p期望 a void *,因此您必须通过它是一个void *,而不是指向任何其他对象类型的指针。

但是请注意,现代编译器可能很聪明,并且他们知道标准 C 函数是如何工作的,因此他们可以只了解函数的标准行为,printf()这样他们就可以向您发出有关此类参数类型不匹配的警告,尽管他们赢了'实际上并没有为你修复它们。

于 2013-10-12T15:44:41.160 回答
3

sizeof返回size_tprintf("%f",...告诉printf下一个参数有 type doublesize_t在内存中有不同的布局,double因此printf错误地解释了这个论点。

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

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

会工作

于 2013-10-12T15:23:49.473 回答
3

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

请注意,size_t大小可以用 表示。unsignedsignedssize_t

这两种类型都在stddef.h标头中定义

C11 标准的 §7.21.6.1 p9

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

于 2013-10-12T15:30:19.550 回答