我正试图解决与向位字段分配时GCC转换警告几乎完全相同的问题,除非所有的解决方案似乎都不起作用。与链接问题一样,gcc版本似乎没有帮助,GCC10.1、9.1、8.2、8.1、7.1、6.1、5.1和4.9.1都失败了。
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;
}编译器产生的看着它在上帝的身上失败。:
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赋值与常量一起工作,但是添加变量会破坏一切。
我通过以下的语用方法解决了这个问题,但这不是一个非常令人满意的解决方案。
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion"
num.b = (5U << 1) | (x & 1U);
#pragma GCC diagnostic pop@Artyr在对这个问题的评论中提出了一个解决方案。如果他把它变成答案,我会接受的。然而,在研究该解决方案时,我发现了另一种解决问题的方法,即实际上没有意义的问题。在下面的示例中,只有最后一个赋值失败。
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,它是从相同的常量静态分配的,解决了这个问题。为什么一个常数和一个变量的组合会导致这个问题?
发布于 2020-05-19 18:07:58
一天后,没有任何答案可供我接受,我将从评论中总结这些发现。
z & 0xf)。
num->b = (5U << 1) x (_Bool)(x & 1);!!可以解决问题。同样,这解决了战术问题,但没有解决更一般的问题(例如,z & 0xf)。
num->b = (5U << 1) x!(X& 1);https://stackoverflow.com/questions/61877799
复制相似问题