C语言 在 C 中指定枚举类型的大小
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4879286/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Specifying size of enum type in C
提问by Will
Already read through this related question, but was looking for something a little more specific.
已经通读了这个相关问题,但正在寻找更具体的东西。
- Is there a way to tell your compiler specifically how wide you want your enum to be?
- If so, how do you do it? I know how to specify it in C#; is it similarly done in C?
- Would it even be worth doing? When the enum value is passed to a function, will it be passed as an
int-sized value regardless?
- 有没有办法特别告诉你的编译器你想要你的枚举有多宽?
- 如果是这样,你怎么做?我知道如何在 C# 中指定它;在 C 中是否类似?
- 它甚至值得做吗?当枚举值传递给函数时,它是否会作为一个
int大小的值传递?
采纳答案by AnT
Is there a way to tell your compiler specifically how wide you want your enum to be?
有没有办法特别告诉你的编译器你想要你的枚举有多宽?
In general case no. Not in standard C.
在一般情况下没有。不在标准 C 中。
Would it even be worth doing?
它甚至值得做吗?
It depends on the context. If you are talking about passing parameters to functions, then no, it is not worth doing (see below). If it is about saving memory when building aggregates from enum types, then it might be worth doing. However, in C you can simply use a suitably-sized integer type instead of enum type in aggregates. In C (as opposed to C++) enum types and integer types are almost always interchangeable.
这取决于上下文。如果您正在谈论将参数传递给函数,那么不,这是不值得做的(见下文)。如果在从枚举类型构建聚合时节省内存,那么它可能值得做。但是,在 C 中,您可以简单地在聚合中使用适当大小的整数类型而不是枚举类型。在 C(与 C++ 相对)中,枚举类型和整数类型几乎总是可以互换的。
When the enum value is passed to a function, will it be passed as an int-sized value regardless?
当枚举值传递给函数时,它是否会作为整数大小的值传递?
Many (most) compilers these days pass all parameters as values of natural word size for the given hardware platform. For example, on a 64-bit platform many compilers will pass all parameters as 64-bit values, regardless of their actual size, even if type inthas 32 bits in it on that platform (so, it is not generally passed as "int-sized" value on such a platform). For this reason, it makes no sense to try to optimize enum sizes for parameter passing purposes.
如今,许多(大多数)编译器将所有参数作为给定硬件平台的自然字长值传递。例如,在 64 位平台上,许多编译器会将所有参数作为 64 位值传递,而不管它们的实际大小,即使类型int在该平台上有 32 位(因此,它通常不会作为“int-在这样的平台上大小”值)。出于这个原因,尝试为参数传递目的优化枚举大小是没有意义的。
回答by Nyx0uf
I believe there is a flag if you are using GCC.
如果您使用 GCC,我相信有一个标志。
-fshort-enums
-fshort-枚举
回答by Kristopher Johnson
You can force it to be at least a certain size by defining an appropriate value. For example, if you want your enum to be stored as the same size as an int, even though all the values would fit in a char, you can do something like this:
您可以通过定义适当的值来强制它至少为特定大小。例如,如果您希望 enum 存储为与 an 相同的大小int,即使所有值都适合 a char,您可以执行以下操作:
typedef enum {
firstValue = 1,
secondValue = 2,
Internal_ForceMyEnumIntSize = MAX_INT
} MyEnum;
Note, however, that the behavior can be dependent on the implementation.
但是请注意,行为可能取决于实现。
As you note, passing such a value to a function will cause it to be expanded to an int anyway, but if you are using your type in an array or a struct, then the size will matter. If you really care about element sizes, you should really use types like int8_t, int32_t, etc.
正如您所注意到的,将这样的值传递给函数将导致它无论如何都被扩展为 int,但是如果您在数组或结构中使用您的类型,那么大小将很重要。如果你真的关心元素的大小,你应该使用类型的喜欢int8_t,int32_t等等。
回答by Patrick Schlüter
There is also another way if the enum is part of a structure:
如果枚举是结构的一部分,还有另一种方法:
struct something {
:0;
enum whatever field:CHAR_BIT;
:0;
};
The :0; can be omitted if the enum field is surrounded by normal fields. If there's another bitfield before, the :0 will force byte alignement to the next byte for the field following it.
:0; 如果枚举字段被普通字段包围,则可以省略。如果之前有另一个位域, :0 将强制字节对齐到它后面的字段的下一个字节。
回答by Julien
In some circumstances, this may be helpful:
在某些情况下,这可能会有所帮助:
typedef uint8_t command_t;
enum command_enum
{
CMD_IDENT = 0x00, //!< Identify command
CMD_SCENE_0 = 0x10, //!< Recall Scene 0 command
CMD_SCENE_1 = 0x11, //!< Recall Scene 1 command
CMD_SCENE_2 = 0x12, //!< Recall Scene 2 command
};
/* cmdVariable is of size 8 */
command_t cmdVariable = CMD_IDENT;
On one hand type command_thas size 8 and can be used for variable and function parameter type.
On the other hand you can use the enum values for assignation that are of type intby default but the compiler will cast them immediately when assigned to a command_ttype variable.
一方面,类型的command_t大小为 8,可用于变量和函数参数类型。另一方面,您可以使用int默认类型的枚举值进行赋值,但编译器将在分配给command_t类型变量时立即强制转换它们。
Also, if you do something unsafe like defining and using a CMD_16bit = 0xFFFF,the compiler will warn you with following message:
此外,如果你做了一些不安全的事情,比如定义和使用 a CMD_16bit = 0xFFFF,,编译器会用以下消息警告你:
warning: large integer implicitly truncated to unsigned type [-Woverflow]
警告:大整数隐式截断为无符号类型 [-Woverflow]
回答by Zak
Even if you are writing strict Ccode, the results are going to be compiler dependent. Employing the strategies from this thread, I got some interesting results...
即使您正在编写严格的C代码,结果也将取决于编译器。使用这个线程中的策略,我得到了一些有趣的结果......
enum_size.c
enum_size.c
#include <stdio.h>
enum __attribute__((__packed__)) PackedFlags {
PACKED = 0b00000001,
};
enum UnpackedFlags {
UNPACKED = 0b00000001,
};
int main (int argc, char * argv[]) {
printf("packed:\t\t%lu\n", sizeof(PACKED));
printf("unpacked:\t%lu\n", sizeof(UNPACKED));
return 0;
}
$ gcc enum_size.c
$ ./a.out
packed: 4
unpacked: 4
$ gcc enum_size.c -fshort_enums
$ ./a.out
packed: 4
unpacked: 4
$ g++ enum_size.c
$ ./a.out
packed: 1
unpacked: 4
$ g++ enum_size.c -fshort_enums
$ ./a.out
packed: 1
unpacked: 1
In my example above, I did not realize any benefit from __attribute__((__packed__))modifier until I started using the C++ compiler.
在我上面的例子中,__attribute__((__packed__))直到我开始使用 C++ 编译器,我才意识到修饰符的任何好处。
EDIT:
编辑:
@technosaurus's suspicion was correct.
@technosaurus 的怀疑是正确的。
By checking the size of sizeof(enum PackedFlags)instead of sizeof(PACKED)I see the results I had expected...
通过检查大小sizeof(enum PackedFlags)而不是sizeof(PACKED)我看到了我预期的结果......
printf("packed:\t\t%lu\n", sizeof(enum PackedFlags));
printf("unpacked:\t%lu\n", sizeof(enum UnpackedFlags));
I now see the expected results from gcc:
我现在看到了来自gcc以下方面的预期结果:
$ gcc enum_size.c
$ ./a.out
packed: 1
unpacked: 4
$ gcc enum_size.c -fshort_enums
$ ./a.out
packed: 1
unpacked: 1
回答by user5057906
It depends on the values assigned for the enums.
这取决于为枚举分配的值。
Ex: If the value greater than 2^32-1 is stored, the size allocated for the overall enum will change to the next size.
例如:如果存储了大于 2^32-1 的值,则为整个 enum 分配的大小将更改为下一个大小。
Store 0xFFFFFFFFFFFF value to a enum variable, it will give warning if tried to compile in a 32 bit environment (round off warning) Where as in a 64 bit compilation, it will be successful and the size allocated will be 8 bytes.
将 0xFFFFFFFFFFFF 值存储到枚举变量中,如果尝试在 32 位环境中编译,它将发出警告(舍入警告),而在 64 位编译中,它将成功并且分配的大小为 8 个字节。
回答by Gabriel Staples
As @Nyx0uf says, GCC has a flag which you can set:
正如@Nyx0uf所说,GCC 有一个您可以设置的标志:
-fshort-enumsAllocate to an enum type only as many bytes as it needs for the declared range of possible values. Specifically, the enum type is equivalent to the smallest integer type that has enough room.
Warning: the -fshort-enums switch causes GCC to generate code that is not binary compatible with code generated without that switch. Use it to conform to a non-default application binary interface.
-fshort-enums分配给枚举类型的字节数仅与声明的可能值范围所需的字节数相同。具体来说,枚举类型相当于有足够空间的最小整数类型。
警告:-fshort-enums 开关会导致 GCC 生成与没有该开关生成的代码二进制兼容的代码。使用它来符合非默认应用程序二进制接口。
Source: https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html
来源:https: //gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html
Additional great reading for general insight:https://www.embedded.fm/blog/2016/6/28/how-big-is-an-enum.
Interesting...notice the line I highlighted in yellow below!
有关一般见解的其他精彩阅读:https : //www.embedded.fm/blog/2016/6/28/how-big-is-an-enum。
有趣……请注意我在下面用黄色突出显示的那条线!
回答by blaizard
Another way is to cast the enum inside a union as follow:
另一种方法是将枚举转换为联合,如下所示:
union char_size {
char a;
enum {
a = 1,
b = 2,
} val;
};
Doing so will force the compiler to fit the enum inside a char.
这样做将强制编译器将枚举放入字符中。


