【问题标题】:-Werror=strict-aliasing error in C-Werror=C 中的严格别名错误
【发布时间】:2018-03-06 19:12:32
【问题描述】:

我正在尝试调用这个函数

static inline void insert(Buffer *buf, double f, size_t index)
{
   insert_64(buf, *(uint64_t *)&f, index);
}

但是,我收到了这个错误:

error: dereferencing type-punned pointer will break strict-aliasing rules [-Werror=strict-aliasing]

不知道我哪里错了。

【问题讨论】:

标签: c


【解决方案1】:

不知道我哪里错了。

*(uint64_t *)&f 打破了严格的别名规则。见Fix for dereferencing type-punned pointer will break strict-aliasing

要修复,请使用memcpy() 以及@dbushunion 的回答。 union 处理严格的别名规则。

void insert2(Buffer *buf, double f, size_t index) {
  union { 
    double d; 
    uint64_t u64;
  } u = { f };
  insert_64(buf, u.u64, index);
}

或者也使用一个复合文字(从C99开始可用)

void insert3(Buffer *buf, double f, size_t index) {
  //             v-----------------------------------------v   compound literal        
  insert_64(buf, (union { double d; uint64_t u64; }){.d = f}.u64, index);
}

对于 C11,我将添加以下内容以供将来评估正确性。

_Static_assert(sizeof (double) == sizeof (uint64_t), "Unexpected sizes");

注意:稀有平台的每个整数和 FP 类型都有不同的 endian

【讨论】:

    【解决方案2】:

    正如 cmets 中提到的,尝试将指向一种类型的指针转​​换为另一种类型的指针会破坏严格的别名规则。您可以通过使用memcpy 将字节从一种类型复制到另一种类型来解决此问题:

    uint64_t x;
    memcpy(&x, &f, sizeof(f));
    

    注意x 包含的内容取决于实现,即double 的表示形式是什么,是系统大端还是小端,是double 64 位等。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-05-31
      • 1970-01-01
      • 2019-01-29
      • 2011-02-15
      • 1970-01-01
      • 2013-03-11
      • 1970-01-01
      • 2013-12-14
      相关资源
      最近更新 更多