ANSI C所有位集类型提升安全字面值与-Wsign转换

ANSI C所有位集类型提升安全字面值与-Wsign转换,c,ansi,C,Ansi,我是否可以将任意宽度的无符号变量中的所有位设置为1s,而不使用相同的文字触发符号转换错误(-Wsign conversion) 没有-Wsign转换,我可以: #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!

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

没有-Wsign转换,我可以:

#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!
我试过(~0)和(~0U),但没有掷骰子。预处理器将第一个提升为int,从而触发-Wsign转换,第二个不提升超过32位的值,只设置64位变量的较低32位

我运气不好吗

编辑:为了澄清,我在整个项目的许多地方使用了定义好的ALL_BITS集,所以我不太愿意在源代码中添加(~(uint32_t)0)和(~(uintptr_t)0)之类的内容。

试试看

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

也许有更清晰的解决方案存在——这一个有点迂腐,但有信心它能满足您的需要。

一的补码将所有的零变为一,反之亦然

所以试试看

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

您得到“负整数隐式转换为无符号类型”警告的原因是
0
是一个文字整数值。作为一个文字整数值,它的类型为
int
,这是一个有符号类型,因此
(~(0))
作为
int
类型的所有位一值,其值为
(int)-1
。当然,将负值非隐式转换为无符号值的唯一方法是显式转换,但您似乎已经拒绝了使用类型合适的强制转换的建议。备选方案:

显然,您还可以通过对无符号
0
求反来消除对无符号类型的隐式转换<代码>(~(0U)),但这样你就只有
无符号整数中的位数了

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

`#define ALL_BITS_VAR(type,name) type name = ~(type)0`
`ALL_BITS_VAR(uint64_t,mask_32);`
但这仍然只适用于声明

有人已经建议使用最广泛的可用类型定义
所有位集
,你拒绝了,理由是开发环境非常严格,但老实说,这是迄今为止最好的方法。如果您的开发环境非常严格,以至于禁止将无符号值赋值给较小类型的无符号变量(其结果定义非常清楚且完全有效),那么您真的没有选择余地,必须执行特定于类型的操作:

#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;
#定义所有位一(类型)(~(类型)0)
uint32\u t掩码\u 32=所有位集(uint32\u t);
uint64\u t mask\u 64=所有位集(uint64\u t);

uintptr\u t mask\u ptr=所有位集(uintptr\u t)如何
~(uint64\u t)0
?感谢chucks,但不幸的是,如果我根据您的建议定义所有位集,则在分配uint32\u t时会中断。我有一个非常严格的开发环境:\n谢谢你的回答,但我一直在寻找一个可以在所有情况下使用的define#如果我不必担心符号转换的问题,那么定义所有位集(-1)将非常有用:(部分解决方案:使用最宽的作为所有位集,然后使用((uint32)所有位集)等等。不幸的是,这个答案仍然触发“负整数隐式转换为无符号类型”在我的开发环境中,我正在为GCC使用-Wsign转换选项。
#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;