2

我可以将任何宽度的无符号变量中的所有位设置为 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) 之类的东西乱扔源代码。

4

3 回答 3

0

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

显然,您还可以通过否定无符号来消除到无符号类型的隐式转换0......(~(0U))但是您将只拥有与unsigned int

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

`#define ALL_BITS_VAR(type,name) type name = ~(type)0`
`ALL_BITS_VAR(uint64_t,mask_32);`

但这仍然只适用于声明。

有人已经建议ALL_BITS_SET使用最广泛的可用类型进行定义,你拒绝了它,理由是拥有一个荒谬的严格的开发环境,但老实说,这是迄今为止最好的方法。如果你的开发环境真的非常严格,禁止将无符号值赋给更小类型的无符号变量,(其结果定义非常明确且完全有效),那么你真的别无选择了,并且必须做一些特定于类型的事情:

#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;

就这样。

(实际上,这还不全部......既然你说你正在使用 GCC,你可以用 GCC 的typeof扩展做一些事情,但我仍然不知道如何在没有你传递的函数宏的情况下使其工作可变为。)

于 2013-07-02T23:41:24.513 回答
0

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

所以试试

#define ALL_BITS_SET (~(0))
uint32_t mask_32 = ALL_BITS_SET;
uint64_t mask_64 = ALL_BITS_SET;
于 2013-07-02T20:08:25.167 回答
0

尝试

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

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

于 2013-07-02T20:00:25.457 回答