为什么枚举的大小只对应单个值的大小?
Why does the size of enum only correspond to the size of a single value?
This post 没有我的问题的答案。
考虑一下:
enum seq {VAL1, VAL2 = 1000000000, VAL3 = UINT_MAX};
int main(void)
{
printf("%lu\n", sizeof(enum seq));
}
这里 UINT_MAX
是 uint32_t
的最大值(40 亿左右)
为什么整个 enum
类型的大小看起来只有 4 个字节?这只够存储一个整数值。
在 C 中,无法获取 enum
中枚举值的个数,也无法获取最大值或最小值。枚举只是定义命名常量值集的便捷方式,但这些值不会存储在任何地方。 sizeof(enum seq)
是编译器用来表示枚举类型值的类型的大小,它是特定于实现的,但必须能够表示所有的枚举常量。在您的示例中,编译器似乎将 uint32_t
用于此类型,因为所有常量都适合此类型,因此 sizeof(enum seq)
在编译时评估为 4
.
但是请注意,C 标准规定了这一点:
6.7.2.2 Enumeration specifiers
...
Constraints
The expression that defines the value of an enumeration constant shall be an integer constant expression that has a value representable as an int
.
Semantics
The identifiers in an enumerator list are declared as constants that have type int
...
Each enumerated type shall be compatible with char
, a signed integer type, or an unsigned integer type. The choice of type is implementation-defined, but shall be capable of representing the values of all the members of the enumeration. The enumerated type is incomplete until immediately after the }
that terminates the list of enumerator declarations, and complete thereafter.
因此 C 标准不允许 UINT_MAX
作为枚举值1,但大多数编译器扩展语义以以编译器特定方式处理更大的枚举类型.如果所有值都适合类型 unsigned int
但不适合 int
,则枚举类型可以是 unsigned int
,但编译器也可以使用 long
甚至 long long
.
另请注意,对于 size_t
类型的值(例如 sizeof(...)
的值),您应该使用 %zu
,或者将值转换为特定的整数类型并使用适当的转换如果您的库不支持 C99 z
转换修饰符,请指定规范。
#include <stdio.h>
enum seq { VAL1, VAL2 = 1000000000, VAL3 = UINT_MAX };
int main(void) {
printf("%d\n", (int)sizeof(enum seq)); // may print 4
return 0;
}
1) 忽略 INT_MAX == UINT_MAX
.
中不太可能的架构
我想也许我开始理解你的问题了。
在您的示例程序中,数字 0
、1000000000
和 UINT_MAX
根本不需要存储在程序的内存中,因为您不使用它们。例如,如果您查看它的 assembly output,您将看不到任何这些数字。这就是评论说它们“无处存储”时的意思。
如果您确实使用了它们,它们很可能会作为立即数直接编码到指令中,就像您使用整数文字 0
或 1000000000
或 4294967295
.例如参见 [=24=].
而在 C 中,sizeof(type)
始终为您提供该类型的 对象 使用的内存量。因此,即使您的编译器确实需要将所有数字 0
、1000000000
和 UINT_MAX
存储在某处的内存中,sizeof(enum seq)
也不会为您提供总数为此所需的内存;它只会为您提供存储一个类型enum seq
对象所需的内存量。由于 4 字节无符号整数足以包含 enum seq
的任何一个可能值,这就是您得到的大小。
This post 没有我的问题的答案。
考虑一下:
enum seq {VAL1, VAL2 = 1000000000, VAL3 = UINT_MAX};
int main(void)
{
printf("%lu\n", sizeof(enum seq));
}
这里 UINT_MAX
是 uint32_t
的最大值(40 亿左右)
为什么整个 enum
类型的大小看起来只有 4 个字节?这只够存储一个整数值。
在 C 中,无法获取 enum
中枚举值的个数,也无法获取最大值或最小值。枚举只是定义命名常量值集的便捷方式,但这些值不会存储在任何地方。 sizeof(enum seq)
是编译器用来表示枚举类型值的类型的大小,它是特定于实现的,但必须能够表示所有的枚举常量。在您的示例中,编译器似乎将 uint32_t
用于此类型,因为所有常量都适合此类型,因此 sizeof(enum seq)
在编译时评估为 4
.
但是请注意,C 标准规定了这一点:
6.7.2.2 Enumeration specifiers
...
Constraints
The expression that defines the value of an enumeration constant shall be an integer constant expression that has a value representable as anint
.Semantics
The identifiers in an enumerator list are declared as constants that have typeint
...Each enumerated type shall be compatible with
char
, a signed integer type, or an unsigned integer type. The choice of type is implementation-defined, but shall be capable of representing the values of all the members of the enumeration. The enumerated type is incomplete until immediately after the}
that terminates the list of enumerator declarations, and complete thereafter.
因此 C 标准不允许 UINT_MAX
作为枚举值1,但大多数编译器扩展语义以以编译器特定方式处理更大的枚举类型.如果所有值都适合类型 unsigned int
但不适合 int
,则枚举类型可以是 unsigned int
,但编译器也可以使用 long
甚至 long long
.
另请注意,对于 size_t
类型的值(例如 sizeof(...)
的值),您应该使用 %zu
,或者将值转换为特定的整数类型并使用适当的转换如果您的库不支持 C99 z
转换修饰符,请指定规范。
#include <stdio.h>
enum seq { VAL1, VAL2 = 1000000000, VAL3 = UINT_MAX };
int main(void) {
printf("%d\n", (int)sizeof(enum seq)); // may print 4
return 0;
}
1) 忽略 INT_MAX == UINT_MAX
.
我想也许我开始理解你的问题了。
在您的示例程序中,数字 0
、1000000000
和 UINT_MAX
根本不需要存储在程序的内存中,因为您不使用它们。例如,如果您查看它的 assembly output,您将看不到任何这些数字。这就是评论说它们“无处存储”时的意思。
如果您确实使用了它们,它们很可能会作为立即数直接编码到指令中,就像您使用整数文字 0
或 1000000000
或 4294967295
.例如参见 [=24=].
而在 C 中,sizeof(type)
始终为您提供该类型的 对象 使用的内存量。因此,即使您的编译器确实需要将所有数字 0
、1000000000
和 UINT_MAX
存储在某处的内存中,sizeof(enum seq)
也不会为您提供总数为此所需的内存;它只会为您提供存储一个类型enum seq
对象所需的内存量。由于 4 字节无符号整数足以包含 enum seq
的任何一个可能值,这就是您得到的大小。