ANSI C All-Bits-Set Type-Promotion Safe Literal with -Wsign-conversion

时间:2013-07-02 16:24:31

标签: c ansi

我可以将任意宽度的无符号变量中的所有位设置为1,而不会使用相同的文字触发符号转换错误(-Wsign-conversion)吗?

没有-Wsign-conversion,我可以:

#define ALL_BITS_SET (-1)
uint32_t mask_32 = ALL_BITS_SET;
uint64_t mask_64 = ALL_BITS_SET;
uintptr_t mask_ptr = ALL_BITS_SET << 12; // here's the narrow problem!

但是在-Wsign-conversion我很难过。

error: negative integer implicitly converted to unsigned type [-Werror=sign-conversion]

我尝试过(〜0)和(~0U),但没有骰子。预处理器将第一个提升为int,触发-Wsign-conversion,第二个不提升过去的32位,只设置64位变量的低32位。

我运气不好吗?

编辑:只是为了澄清,我在整个项目的许多地方都使用了定义的ALL_BITS_SET,所以我犹豫是否使用像(〜(uint32_t)0)和(〜(uintptr_t)0)这样的东西乱丢垃圾。< / p>

3 个答案:

答案 0 :(得分:0)

尝试

uint32_t  mask_32  = ~((uint32_t)0);
uint64_t  mask_64  = ~((uint64_t)0);
uintptr_t mask_ptr = ~((uintptr_t)0);

可能存在更清晰的解决方案 - 这个解决方案有点迂腐,但相信它能满足您的需求。

答案 1 :(得分:0)

一个补码将全零改为1,反之亦然。

所以试试

#define ALL_BITS_SET (~(0))
uint32_t mask_32 = ALL_BITS_SET;
uint64_t mask_64 = ALL_BITS_SET;

答案 2 :(得分:0)

您收到警告“隐式转换为无符号类型的负整数”的原因是0是一个文字整数值。作为文字整数值,类型为int的类型为(~(0)),因此int为类型为(int)-1的全位一值,其值为{{ 1}}。当然,非负隐含地将负值转换为无符号值的唯一方法是明确地执行此操作,但您似乎已经拒绝了使用类型适当的强制转换的建议。备选方案:

显然,你也可以通过否定无符号0 ... (~(0U))来消除隐式转换为无符号类型,但是你只能拥有{{1}中的位数。 }

编写一个稍微不同的宏,并使用宏来声明变量

unsigned int

但这仍然只适用于声明。

有人已经建议使用最广泛的可用类型定义`#define ALL_BITS_VAR(type,name) type name = ~(type)0` `ALL_BITS_VAR(uint64_t,mask_32);` ,你因为有一个荒谬严格的开发环境而拒绝了,但老实说,这是迄今为止最好的方法。如果您的开发环境非常严格,禁止将无符号值分配给较小类型的无符号变量(结果非常清晰且完全有效),那么您真的没有选择了,并且必须做一些特定类型的事情:

ALL_BITS_SET

就是这样。

(实际上,那不是相当所有...因为你说你正在使用GCC,你可以用GCC的#define ALL_BITS_ONE(type) (~(type)0) uint32_t mask_32 = ALL_BITS_SET(uint32_t); uint64_t mask_64 = ALL_BITS_SET(uint64_t); uintptr_t mask_ptr = ALL_BITS_SET(uintptr_t) << 12; 扩展做一些事情,但我仍然不喜欢看看如何在没有将变量传递给的函数宏的情况下使其工作。)