如何在GCC中强制枚举大小?
如何在GCC中强制枚举大小?
已经阅读过这个相关问题,但是想要更具体的信息。
- 有没有办法告诉编译器你想要多宽的枚举类型?
- 如果有,你如何做到?我知道如何在C#中指定它;在C中是否也是这样做的?
- 这样做是否值得?当枚举值传递给函数时,它会作为一个
int
大小的值传递吗?
问题的原因是在使用C++编译器时,枚举类型的大小受到编译器选项的影响,而在使用C编译器时,枚举类型的大小不受编译器选项的影响。
解决方法是使用sizeof(enum PackedFlags)
来检查枚举类型的大小,而不是使用sizeof(PACKED)
。这样可以确保枚举类型不会被扩展。
以下是一个示例程序:
#includeenum __attribute__((__packed__)) PackedFlags { PACKED = 0b00000001, }; enum UnpackedFlags { UNPACKED = 0b00000001, }; int main (int argc, char * argv[]) { printf("packed:\t\t%lu\n", sizeof(enum PackedFlags)); printf("unpacked:\t%lu\n", sizeof(enum UnpackedFlags)); return 0; }
在使用C++编译器编译时,可以通过添加-fshort_enums
选项来强制枚举类型的大小为1:
$ g++ enum_size.c -fshort_enums $ ./a.out packed: 1 unpacked: 1
而在使用C编译器编译时,不需要任何选项,枚举类型的大小就是符合预期的:
$ gcc enum_size.c $ ./a.out packed: 1 unpacked: 4
通过使用sizeof(enum PackedFlags)
来检查枚举类型的大小,可以避免C编译器下枚举类型大小不符合预期的问题。
在C语言中,不能直接告诉编译器我们希望枚举的大小是多少。这取决于上下文。如果是关于将参数传递给函数,那么没有必要这样做。因为大多数编译器会根据硬件平台的自然字长传递参数。例如,在64位平台上,许多编译器会将所有参数作为64位值传递,而不管它们的实际大小,即使在该平台上int类型仅有32位(因此,在这样的平台上,它不会被传递为"int-sized"值)。因此,试图为了参数传递目的而优化枚举的大小是没有意义的。
然而,如果是为了在构建聚合类型时节省内存,可能值得这样做。在C语言中,可以在聚合类型中使用适当大小的整数类型来替代枚举类型。在C语言中,枚举类型和整数类型几乎可以互相替换。因此,如果我们需要控制枚举的大小,可以考虑使用整数类型来代替。
需要注意的是,如果我们在一个8位处理器上使用枚举类型,其自然大小是8位,而int和enum类型至少为16位(没有使用-fshort-enums选项的情况下),因此至少需要2个寄存器来存储枚举类型,这可能会降低函数调用的速度。
不能直接告诉编译器我们希望枚举的大小是多少,但可以通过选择适当大小的整数类型来代替枚举类型来实现类似的效果。
GCC编译器中有一个标志-fshort-enums
,可以强制设置枚举的大小。另外,也可以使用__attribute__((__packed__))
来选择性地设置枚举的大小。
根据GCC文档的说法,使用-fshort-enums
标志是危险的,因为它会影响所有的枚举类型。更好的做法是使用__attribute__((__packed__))
来设置枚举的大小。