这里有一个问题:
#include
typedef enum {
CAN1 = 1,
CAN2,
CAN3,
CAN4,
} Enum_8bit;
typedef enum {
IP4 = 0x1234,
IP5 = 0x444,
IP6 = 0xffee,
} Enum_16bit;
void main(void)
{
printf("Enum_8bit is %d.\n", sizeof(Enum_8bit));
printf("Enum_16bit is %d.\n", sizeof(Enum_16bit));
printf("Enum_8bit element is %d.\n", sizeof(CAN1));
printf("Enum_16bit element is %d.\n", sizeof(IP6));
Enum_16bit bit16 = IP4;
Enum_8bit bit8 = CAN1;
printf("Enum_8bit variable is %d.\n", sizeof(bit8));
printf("Enum_16bit variable is %d.\n" , sizeof(bit16));
}
一般情况下,上面会打印的结果是什么呢?
对于一个32位的系统来说,如果你是用的GCC,而且CFLAGS是在默认的情况的话,上面输出的都是4.
Enum_8bit is 4.
Enum_16bit is 4.
Enum_8bit element is 4.
Enum_16bit element is 4.
Enum_8bit variable is 4.
Enum_16bit variable is 4.
Enum_8bit 和Enum_16bit在这里,只是一个申明的数据类型,它和int, char一样,只不过是我们用户自己申请的数据类型,它的大小就是它的变量所占有的空间的大小。而不是所有它的element总合的大小。
我的系统是一个64位的系统,为什么这里输出的是4个字节大小,而不是8个字节的大小者 2个字节呢?这里因为在C的standard中:
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.
[...]
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.
enum类型就是一个int 类型,但它占用空间到底有多大呢? 我没有找到相关的文档说明,我个人认为这个取决于你的系统的字节对齐方式和enum中各个元素所给于的值的大小,像上面,我的例子,Enum_8bit 每一个元素的值都没有超过8bit,但及时这样,因为我的系统是以4字节对齐的,C compiler 分配了4个字节大小给这个类型。Enum_16bit也一样,以四字节对齐。
这不是有点浪费空间吗?能不能缩短它们的大小,让它们根据各自元素的大小来分配大小呢?
是可以的,我们可以用 -fshort-enums,强制改变enum的大小。
如:gcc -g -O2 -o -fshort-enums enum_test enum-test.o
Enum_8bit is 1.
Enum_16bit is 2.
Enum_8bit element is 4.
Enum_16bit element is 4.
Enum_8bit variable is 1.
Enum_16bit variable is 2.
但是奇诡,为什么Enum_8bit和Enum_16bit中的元素还是4字节呢?原来对于enum来说,它自己的每一个element就是一个正型,大小取决于它的值,而默认是四字节对齐。
如我把上面的程序改成这样:
#include
typedef enum {
CAN1 = 1,
CAN2,
CAN3,
CAN4,
} Enum_8bit;
typedef enum {
IP4 = 0x1234,
IP5 = 0x444,
IP6 = 0xffee,
} Enum_16bit;
typedef enum {
VP1 = 0x1234,
VP2 = 0x444,
VP3 = 0xffeeEEEEEEEEEDDE,
} Enum_32bit;
void main(void)
{
printf("Enum_8bit is %d.\n", sizeof(Enum_8bit));
printf("Enum_16bit is %d.\n", sizeof(Enum_16bit));
printf("Enum_8bit element is %d.\n", sizeof(CAN1));
printf("Enum_16bit element is %d.\n", sizeof(IP4));
printf("Enum_32bit 64bits element is %d.\n", sizeof(VP3));
printf("Enum_32bit 16bits element is %d.\n", sizeof(VP2));
Enum_16bit bit16 = IP4;
Enum_8bit bit8 = CAN1;
printf("Enum_8bit variable is %d.\n", sizeof(bit8));
printf("Enum_16bit variable is %d.\n" , sizeof(bit16));
}
在有 -fshort-enums 的情况下:
gcc -g -O2 -fshort-enums -o enum_test enum-test.o
它的输出结果是:
Enum_8bit is 1.
Enum_16bit is 2.
Enum_8bit element is 4.
Enum_16bit element is 4.
Enum_32bit 64bits element is 8.
Enum_32bit 16bits element is 4.
Enum_8bit variable is 1.
Enum_16bit variable is 2.
在没有 -fshort-enums的情况下:
Enum_8bit is 4.
Enum_16bit is 4.
Enum_8bit element is 4.
Enum_16bit element is 4.
Enum_32bit 64bits element is 8.
Enum_32bit 16bits element is 4.
Enum_8bit variable is 4.
Enum_16bit variable is 4.