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

Viv*_*rma 58 c enums const c-preprocessor

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

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

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

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

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

"因此它是实现定义的,而sizeof(枚举)可能等于sizeof(char),即1."

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

Joh*_*itb 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));
Run Code Online (Sandbox Code Playgroud)

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

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

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

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


对编辑的回应

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

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

但是如果你指定一个-1,那么GCC选择使用兼容int的类型X

int main(void) {
  enum X { A = -1 };
  enum X a; // X compatible with "int"
  int *p = &a;
}
Run Code Online (Sandbox Code Playgroud)

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

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

  • 枚举和#defines之间并没有完全不同:正如你所说的#defines,编译器甚至看不到初始标记,因为它被预处理器替换为实际值.虽然编译器确实看到了枚举,但如果使用调试符号编译代码,调试器将显示枚举标签而不是它们的值,这极大地有助于调试. (9认同)

Mar*_*wis 19

C99,6.7.2.2p4说

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

脚注108补充道

实现可以延迟选择哪个整数类型,直到看到所有枚举常量.

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

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

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


IRB*_*BMe 13

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

ANSI C标准说:

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

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

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

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

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

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


INS*_*INS 5

不。

示例:CodeSourcery 编译器

当您像这样定义枚举时:

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)
Run Code Online (Sandbox Code Playgroud)

他们的邮件列表中的详细信息

  • 这不是真的......它依赖于实现......这两个代码在我的系统上都给出了 4 的输出。平台 - Ubuntu 10.04(32 位),gcc 编译器 (4认同)