【问题标题】:Why does the sizeof responses differently to %f?为什么 sizeof 响应与 %f 不同?
【发布时间】:2013-10-12 15:21:53
【问题描述】:

为什么我没有得到与%d%f 相同的值?

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

输出:2.168831

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

输出:4

【问题讨论】:

  • printf("%f",sizeof(arr)); 未定义,其次不要使用void main 使用int main
  • 因为%f 需要double,而您传递给它的是size_t。这是未定义的行为。
  • @GrijeshChauhan 你为什么说它未定义?你的意思是 %f 只需要双精度值吗?
  • @Shanpriya 阅读下面的更新答案。
  • @Shanpriya 一个很好的参考C Printf and Scanf Reference

标签: c gcc escaping sizeof


【解决方案1】:

为了给出更多解释,这是因为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 时,它会将其解释为int,当它误解了位模式(并且,在这种情况下,可能是参数的大小,以及,将它扔给它之后的任何其他参数)。

这就是为什么这些函数是在 C 中实际上需要强制转换为 void * 的少数情况之一的原因,因为指向不同类型对象的指针允许具有不同的大小,并且因为 @ 987654337@ 需要 void *,您必须将 void * 传递给它,而不是指向任何其他对象类型的指针。

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

【讨论】:

    【解决方案2】:

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

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

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

    会工作

    【讨论】:

    • 正确的格式字符串是%zu for sizeof(在mcrosoft中使用%lu
    • so %zu 用于定义 sizeof 甚至 %d 是错误的声明方式?
    • @simonc 我认为从C standard (6.5.2.2 paragraph 6) 添加"If a conversion specification is invalid, the behavior is undefined" OP 在对我发表评论时表示怀疑。
    【解决方案3】:

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

    注意size_tunsignedsigned的大小可以用ssize_t来表示。

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

    §7.21.6.1 p9 of the C11 标准

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

    【讨论】:

      猜你喜欢
      • 2012-06-14
      • 2019-08-17
      • 2021-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-15
      相关资源
      最近更新 更多