在许多情况下,需要将值为0x00
、0x01
和0x02
的常量强制转换为unsigned int
类型或加上后缀u
/U
。这些常量本身是int
类型的,对于一些位操作,对int
类型的值进行位移可能会出现问题,例如将它们左移到符号位置时可能发生的情况!
如果你将值为0x02(int)左移至第31:30位,则会发生这种情况!因此,
0x02 << 30
在32位宽度整数的机器上,该行为未定义,然而...
0x02U << 30
或者
((uint32_t)0x02) << 30
不会。
在 C 语言中,枚举列表的标识符声明为 (C11 6.7.2.2p3)
常量是 int 类型,并且可以出现在任何允许使用 int 的地方。
也就是说,这些常量在进行位移操作时也需要进行类型转换。
请注意,在 C 语言中,枚举常量的类型不一定是枚举本身的类型:
#include <stdio.h>
enum foo {
bar = 42
};
int main(void) {
printf("An enumeration constant is an %s\n",
_Generic(bar,
int: "int",
unsigned int: "unsigned int",
default: "something else"));
printf("On this implementation the enum foo is %s\n",
_Generic((enum foo) 0,
int: "int",
unsigned int: "unsigned int",
default: "something else"));
}
在GCC上,这将打印出枚举常量类型的,以及的类型的。也就是说,常量具有与实际枚举不同的类型。
此外,使用超出整数范围的枚举常量是一种约束违规;由于0x80000000在32位系统上不能表示为,因此无法在可移植性方面用作枚举常量。
% gcc enumtest.c -std=c11 -pedantic
enumtest.c:5:11: warning: ISO C restricts enumerator values to range of ‘int’
[-Wpedantic]
5 | bar = 0x80000000
| ^~~~~~~~~~
最后,由于C标准规定枚举类型本身的类型由编译器决定,因此一些编译器可能会将短枚举类型使用无符号字符(unsigned char)。即使在这种情况下,您可能仍需要进行强制转换,因为在进行算术运算之前,
unsigned char
将被升级为
signed int
而不是
unsigned int
。
sizeof(int)
是多少? - 001