【问题标题】:int * vs float * typeint * vs float * 类型
【发布时间】:2014-05-25 06:54:58
【问题描述】:

给定以下 sn-p 代码:

int *iptr;
float *fptr;
float fval;
fval = 0.0;
fptr = &fval;
iptr = fptr;
printf("%d \n", *iptr);
fval = 1.0;
printf("%d \n", *iptr);

输出是:

0
1065353216

为什么第一个打印语句至少与 *iptr (0.0) 关联的值大致匹配,而第二个打印语句不匹配?

【问题讨论】:

  • 试试printf("%d", fval);
  • 阅读浮点数的表示。那你就明白了。
  • 一个很好的浮点表示初学者参考可以在这里找到:floating-point-gui.de。

标签: c pointers floating-point assign


【解决方案1】:

语句iptr = fptr; 将调用未定义的行为。

因此推测结果没有多大意义。

【讨论】:

  • 为什么是未定义的行为
  • 因为您实际上是在对不相关的指针类型进行强制转换。
  • @Bathsheba 您能否引用标准中的相关部分,这解释了这一点?
  • 我在咖啡店,所以不能。但这更像是(int*)(void*)(float*)&fval,我们都知道是UB。
【解决方案2】:

这是一个未定义的行为:iptr = fptr;。您不能将浮点数打印为 int,浮点数存储在 IEEE754 format

你需要试试这个:

printf("%d", fval);

【讨论】:

    【解决方案3】:

    零浮点数由零组成。任何其他数字不仅仅是数字,而是指数和尾数 - 当然它们都不是你的数字。

    【讨论】:

      【解决方案4】:

      当您编写printf("%d \n", *iptr); 时,您要求printf 将iptr 指向的值解释为整数。

      碰巧0 的float 版本由0 的int 版本的相同位表示。特别是,位都是0。

      但是,任意浮点数,例如 1.0 将具有不同的位表示(由 IEEE 标准定义),当解释为 int 时,这将毫无意义。

      Wikipedia article 解释了浮点数如何表示为位。

      【讨论】:

      • @merlin2011:严格别名在这里不是问题吗? (例如,这里:stackoverflow.com/questions/98650/…,“所以基本上,如果你有一个 int* 和一个 float* 他们不允许指向同一个内存位置。如果你的代码不尊重这一点,那么编译器的优化器很可能会中断你的代码。”
      • @dmcr_code 绝对是。这就是为什么我添加了自己的答案。
      • @ajay:是的,我认为必须提及; (不幸的是)C有很多“讨厌”的细节需要知道(我自己最近熟悉了其中的一些,比如这个,或者有符号/无符号混合等)
      • @dmcr_code 编写安全、符合标准的 C 代码绝非易事,需要认真努力。我自己正在努力学习。
      • @ajay: 标准合规性是smth到目前为止我还没有“考虑过”,我通常尝试用我所学的东西(例如,使用书籍)来写,而不是重新发明轮子并尝试避免一些神秘的表达等,并注意像这样的陷阱
      【解决方案5】:

      浮点数以 IEEE754 格式存储,其中 1.0 等数字的值与 1 完全不同(它是偏移量以允许负数和指数)。您不能将浮点数打印为 int 并且结果类似于分配给浮点数的数字。

      【讨论】:

        【解决方案6】:

        @merlin 非常清楚地解释了您的代码输出。但是,还有更多内容,因此我将在此处添加。您的代码违反了strict aliasing rule 并调用了未定义的行为。严格的别名规则意味着不同的指针类型不应指向相同的内存位置。

        iptr = fptr;
        

        iptr 是 int * 类型,fptr 是 float * 类型。该语句将fptr 分配给iptr——一种不同的类型——这意味着现在两者都指向fval。这打破了严格的别名规则。这会导致未定义的行为,这意味着不可预测的行为。该标准对处理此类情况的实施没有要求。简而言之,您应该避免导致未定义行为的代码。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-02-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-12-03
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多