sizeof(enum)== sizeof(int),总是吗?

时间:2009-07-11 14:40:53

标签: c enums const c-preprocessor

sizeof(enum)== sizeof(int),总是吗?

  • 或者它依赖于编译器吗?
  • 说错了,因为编译器针对字长(内存对齐)进行了优化,即y int是特定编译器上的字大小?如果我使用枚举,这是否意味着没有处理惩罚,因为它们将是单词对齐的?
  • 如果我把所有返回代码都放在枚举中是不是更好,因为我显然不担心它获得的值,只检查返回类型时的名称。如果是这种情况,#DEFINE会更好,因为它可以节省内存。

通常的做法是什么? 如果我必须通过网络传输这些返回类型,并且必须在另一端进行某些处理,那么您更喜欢枚举/ #sninition / const ints。

编辑 - 只是检查网络,因为编译器没有象征性地链接宏,人们如何调试然后将整数值与头文件进行比较?

来自答案 - 我在下面添加这一行,因为我需要澄清 -

  

“所以它是实现定义的,并且   sizeof(enum)可能等于   sizeof(char),即1。“

  • 这是否意味着编译器检查枚举中的值范围,然后分配内存。我不这么认为,当然我不知道。有人可以解释一下“可能是什么”。

6 个答案:

答案 0 :(得分:34)

它取决于编译器,可能在枚举之间有所不同。以下是语义

enum X { A, B };

// A has type int
assert(sizeof(A) == sizeof(int));

// some integer type. Maybe even int. This is
// implementation defined. 
assert(sizeof(enum X) == sizeof(some_integer_type));

请注意,C99中的“某些整数类型”也可能包含扩展整数类型(但是,如果提供它们,则必须记录实现)。枚举的类型是某种类型,可以存储任何枚举器的值(在这种情况下为AB)。

我认为使用枚举不会有任何处罚。枚举器也是整型常量表达式(例如,您可以使用它来初始化静态或文件范围变量),并且我尽可能地将它们放在宏中。

枚举器不需要任何运行时内存。只有在创建枚举类型的变量时,才可以使用运行时内存。只需将枚举数视为编译时常量。

我只想使用一种类型,它可以存储枚举器值(我应该知道之前的粗略值范围),强制转换为它,然后通过网络发送它。优选地,类型应该是一些固定宽度的类型,例如int32_t,因此当涉及不同的机器时它不会发生冲突。或者我会打印数字,并在另一边扫描它,这摆脱了一些这些问题。


对编辑的回应

好吧,编译器不需要使用任何大小。一个简单的事情是,值的符号很重要 - 无符号类型在某些计算中可以显着提升性能。以下是GCC 4.4.0在我的方框中的行为

int main(void) {
  enum X { A = 0 };
  enum X a; // X compatible with "unsigned int"
  unsigned int *p = &a;
}

但如果您指定了-1,那么GCC选择使用int作为X

兼容的类型
int main(void) {
  enum X { A = -1 };
  enum X a; // X compatible with "int"
  int *p = &a;
}

使用GCC的--short-enums选项,使其使用仍然适合所有值的最小类型。

int main() {
  enum X { A = 0 };
  enum X a; // X compatible with "unsigned char"
  unsigned char *p = &a;
}

答案 1 :(得分:19)

C99,6.7.2.2p4说

  

每个枚举类型应为   与char兼容,签名   整数类型或无符号   整数类型。选择类型   是实现定义的,108)但是   应该能够代表   所有成员的价值观   列举。 [...]

脚注108添加

  

实现可能会延迟选择哪个整数   键入,直到看到所有枚举常量。

因此它是实现定义的,sizeof(enum)可能等于sizeof(char),即1。

在选择一小部分整数的大小时,总是一个惩罚。如果你在内存中做的很小,可能会有一个处理惩罚;如果你把它做得更大,就会有空间罚款。这是一个时空交换。

错误代码通常是#defines,因为它们需要是可扩展的:不同的库可能会添加新的错误代码。你不能用枚举来做到这一点。

答案 2 :(得分:13)

  

sizeof(enum)== sizeof(int),总是

ANSI C标准说:

  

每个枚举类型应与char,有符号整数类型或无符号整数类型兼容。类型的选择是实现定义的。 (6.7.2.2枚举规范)

所以我认为这意味着没有。

  

如果是这种情况,#DEFINE会更好,因为它可以节省内存。

使用枚举以什么方式使用枚举来节省内存?枚举只是一种允许您向编译器提供更多信息的类型。在实际生成的可执行文件中,它只是转换为整数,就像预处理器将使用 #define 创建的宏转换为其值一样。

  

通常的做法是什么。我是否必须通过网络传输这些返回类型,并且必须在另一端完成一些处理

如果您计划通过网络传输值并在另一端处理它们,则应定义协议。确定每种类型的位大小,字节顺序(字节的顺序),并确保在客户端和服务器代码中都遵循该大小。也不要只是假设因为它恰好工作,你就做对了。例如,您所选择的客户端和服务器平台上的endianess可能匹配,但情况可能并非总是如此。

答案 3 :(得分:4)

没有

示例:The CodeSourcery compiler

定义这样的枚举时:

enum MyEnum1 {
A=1,
B=2,
C=3
};
// will have the sizeof 1 (fits in a char)

enum MyEnum1 {
A=1,
B=2,
C=3,
D=400
};
// will have the sizeof 2 (doesn't fit in a char)

Details来自他们的邮件列表

答案 4 :(得分:2)

在某些编译器上,枚举的大小取决于枚举中的条目数。 (少于255个Entrys =>字节,超过255个Entrys int) 但这取决于编译器和编译器设置。

答案 5 :(得分:0)

enum fruits {apple,orange,strawberry,grapefruit};  
char fruit = apple;  
fruit = orange;  
if (fruit < strawberry)  
...  

所有这些都能完美地发挥作用
如果要为枚举实例使用特定的基础类型,请不要使用该类型本身。