-Werror = C中的严格别名错误

时间:2018-03-06 19:12:33

标签: c

我正在尝试调用此函数

CHANNEL_ID

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

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

不知道我哪里出错了。

2 个答案:

答案 0 :(得分:1)

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

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

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

答案 1 :(得分:1)

  

不知道我哪里出错了。

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

要解决此问题,请使用memcpy(),以及@dbushunionunion处理严格别名规则。

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