【问题标题】:Why does casting this pointer change the value pointed too为什么投射这个指针也会改变指向的值
【发布时间】:2017-07-17 17:01:21
【问题描述】:

我有一个函数返回一个unsigned long,它实际上是一个float

我们将调用该函数unsigned long foo()

当我像这样调用 printf 时:

printf("%f", foo());

它总是会打印出0.00000

但是当我这样投射时:

unsigned long bar = foo();
printf("%f", *((float *)(&bar)));

它正确输出浮点数。

使用"%x" 打印我可以看到二进制表示不同。令人惊讶的是,unsigned long 版本看起来更像是一个实际的浮点表示(41ba019a vs 40000000

我在我的系统上仔细检查了unsigned longfloat 的大小是否相同。

所以我的问题是:

这样转换指针如何改变所指向的值?

编辑: foo() 的相关部分本质上是

unsigned long foo()
{
  float a = 22.4;
  return *(unsigned long *)(&a) ;
}

【问题讨论】:

  • 你没有向我们展示最重要的事情。让我们看看foo()
  • unsigned long 的值是从浮点开始转换的。该函数可以根据参数返回不同的类型。
  • 所以?让我们看看相关的部分。
  • 这不是因为float在传递给函数时首先被提升为double,所以printf期望将double打印为float吗?由于 foo 不返回浮点数,因此不执行转换,因此为 0.0000。
  • 这是一个非常糟糕的代码。如果您希望该函数返回不同的类型,请使其与所有可能类型的union 一起使用并返回它。不要这样重新解释。这将有助于避免此类问题和其他潜在的 UB。

标签: c casting


【解决方案1】:

这是因为浮点数在传递给函数时首先被提升为双精度,因此 printf 期望打印双精度。由于foo 不返回浮点数,因此不会执行转换,因此 printf 会找到其他内容作为参数。

【讨论】:

  • float 升级为double 是特定于可变参数函数(例如printf()),而不是所有函数。
  • @Clifford,你有参考资料吗(只是为了我的好奇心)?我不知道。
  • ...好吧,这还不是全部。 float 没有原型的函数的参数也被提升。例如,如果您声明了void fn(),但调用了fn( 1.0f ),则该参数也将提升为double。但这些是函数完全原型化的常见情况的例外。 stackoverflow.com/questions/1255775/…。注意不适用于 void fn()void fn( void ) 相同的 C++。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-09-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多