首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >分配给位字段时GCC之子的转换警告

分配给位字段时GCC之子的转换警告
EN

Stack Overflow用户
提问于 2020-05-18 19:47:02
回答 1查看 393关注 0票数 2

我正试图解决与向位字段分配时GCC转换警告几乎完全相同的问题,除非所有的解决方案似乎都不起作用。与链接问题一样,gcc版本似乎没有帮助,GCC10.1、9.1、8.2、8.1、7.1、6.1、5.1和4.9.1都失败了。

代码语言:javascript
复制
typedef unsigned int uint;
struct foo { uint a:8; uint b:24; };
void bar(struct foo num, uint x) {
    num.b = (5U << 1) | (1 & 1);
    num.b = ((uint)(((5U << 1) | (uint)((uint) x & 1))) & 0xffffffU);
    num.a = (unsigned char)x;
}

编译器产生的看着它在上帝的身上失败。

代码语言:javascript
复制
In function 'bar':
5:13: error: conversion from 'unsigned int' to 'unsigned int:24' may change value [-Werror=conversion]
    5 |     num.b = ((uint)(((5U << 1) | (uint)((uint) x & 1))) & 0xffffffU);
      |             ^

正如您所看到的,我尝试显式地掩蔽24位,将随机的东西投射到无符号int,以及几乎所有上面的组合(例如,只是掩蔽,只是抛出,在看似任何相关的位置,等等)。第一个num.b赋值与常量一起工作,但是添加变量会破坏一切。

我通过以下的语用方法解决了这个问题,但这不是一个非常令人满意的解决方案。

代码语言:javascript
复制
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion"
    num.b = (5U << 1) | (x & 1U);
#pragma GCC diagnostic pop

@Artyr在对这个问题的评论中提出了一个解决方案。如果他把它变成答案,我会接受的。然而,在研究该解决方案时,我发现了另一种解决问题的方法,即实际上没有意义的问题。在下面的示例中,只有最后一个赋值失败。

代码语言:javascript
复制
uint z = 5U;
num.b = (5U << 1) | (1 & 1); //OK
num.b = ((z << 1) | (x & 1)) & 0xffffffU; //OK
num.b = ((5U << 1) | (x & 1)) & 0xffffffU; //BAD

我不明白的是,为什么添加另一个变量z,它是从相同的常量静态分配的,解决了这个问题。为什么一个常数和一个变量的组合会导致这个问题?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-05-19 18:07:58

一天后,没有任何答案可供我接受,我将从评论中总结这些发现。

  • @Artyer发现将变量转换为布尔值可以解决这个问题。这解决了战术问题,但没有解决更一般的问题(例如,z & 0xf)。 num->b = (5U << 1) x (_Bool)(x & 1);
  • @M.M独立地发现了我假设的结果,结果是相同的效果(转换为布尔值)。使用!!可以解决问题。同样,这解决了战术问题,但没有解决更一般的问题(例如,z & 0xf)。 num->b = (5U << 1) x!(X& 1);
  • 在研究上述解决方案时,我发现将表达式的“常量”一侧存储到变量中通常可以解决问题。 无符号int z= 5U;num->b = (z << 1) x&1;
  • @yugr认为这是一个bug。Bug 95213与gcc一起开启了追踪这一过程的通道。
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61877799

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档