C中枚举器列表中枚举常量的类型
type of enumeration constants inside enumerator list in C
已编辑
我目前正在开发一个多平台枚举解析器,在尝试回答上述问题时发现了这种奇怪的行为。
问题A)
C标准是否在枚举声明完成之前确定枚举常量的类型?
以Keil ARMCC为例:
enum e {
VAL0 = (signed char)126,
VAL1,
VAL2,
SIZE0 = sizeof(VAL0),
SIZE1 = sizeof(VAL1),
SIZE2 = sizeof(VAL2)
};
我得到 SIZE0 = 1,SIZE1 = 1,SIZE2 = 8。
(如果我评估定义之外的枚举常量的大小,所有的大小都是 int)。
他们不应该都等于 sizeof( int ) 吗?
(请记住,在本例中,int 的大小为 4 个字节。)
问题B)
对于Keil C251,我有以下内容:
signed int VALUE0 = (signed char)-1;
enum{ VALUE1 = (signed char)-1 };
enum{ VALUE2 = -1 };
printf( "Is VALUE0 equal to VALUE1? ---> %s", VALUE0 == VALUE1 ? "Yes!" : "No!" );
printf( "Is VALUE0 equal to VALUE2? ---> %s", VALUE0 == VALUE2 ? "Yes!" : "No!" );
打印:
Is VALUE0 equal to VALUE1? ---> No!
Is VALUE0 equal to VALUE2? ---> Yes!
不应该都打印 yes 吗?
我遗漏的 VALUE0 和 VALUE1 的定义之间是否存在差异,也许是类型转换?或者这可能是编译器错误?
在 C 中(与 C++ 不同),枚举常量的类型为 int
。在类型声明结束之前引用枚举常量是合法的。
如果 Keil ARMCC 给你 sizeof(VAL0) != sizeof (int)
,其中 VAL0
是一个枚举常量,那么 Keil ARMCC 就不是一个符合规范的 C 编译器。我在这里看到其他问题表明它不符合要求。
不符合规范不一定是编译器错误(除非供应商声称它符合规范,但据我所知他们没有)。
关于 B 部分:
enum e{
MIN_SIGNED_CHAR_0 = (signed char)( -128 ),
MIN_SIGNED_CHAR_1 = -128,
MIN_SIGNED_CHAR_2 = ( signed int)(signed char)( -128 ),
MIN_SIGNED_CHAR_3 = (unsigned int)(signed char)( -128 ),
MIN_SIGNED_CHAR_0_PLUS_1 = MIN_SIGNED_CHAR_0 + 1,
MIN_SIGNED_CHAR_1_PLUS_1 = MIN_SIGNED_CHAR_1 + 1,
MIN_SIGNED_CHAR_2_PLUS_1 = MIN_SIGNED_CHAR_2 + 1,
MIN_SIGNED_CHAR_3_PLUS_1 = MIN_SIGNED_CHAR_3 + 1,
};
几乎所有符合规范的 C 编译器都应该为 MIN_SIGNED_CHAR_{0,1,2}
常量提供值 -128
(int
类型),为 MIN_SIGNED_CHAR_{0,1,2}_PLUS_1
常量提供值 -127
(也是 int
类型)。唯一可能的摆动空间是使用 SCHAR_MIN == -127
的实现,这是可能的但不太可能,并且显然 而不是 Keil 编译器的情况。如果您得到不同的结果,要么是编译器中的错误。
但是MIN_SIGNED_CHAR_3
的定义是有问题的。 int
值 -128
转换为 signed char
,这不会更改值。然后将其转换为 unsigned int
,得到 UINT_MAX+1-128
(假设 32 位,这是 4294967168
)。指定值超出 int
范围的枚举常量是违反约束的,需要进行诊断。 (你收到编译时警告了吗?)如果编译器不拒绝该程序,结果是未定义的。
已编辑
我目前正在开发一个多平台枚举解析器,在尝试回答上述问题时发现了这种奇怪的行为。
问题A)
C标准是否在枚举声明完成之前确定枚举常量的类型?
以Keil ARMCC为例:
enum e {
VAL0 = (signed char)126,
VAL1,
VAL2,
SIZE0 = sizeof(VAL0),
SIZE1 = sizeof(VAL1),
SIZE2 = sizeof(VAL2)
};
我得到 SIZE0 = 1,SIZE1 = 1,SIZE2 = 8。 (如果我评估定义之外的枚举常量的大小,所有的大小都是 int)。
他们不应该都等于 sizeof( int ) 吗? (请记住,在本例中,int 的大小为 4 个字节。)
问题B)
对于Keil C251,我有以下内容:
signed int VALUE0 = (signed char)-1;
enum{ VALUE1 = (signed char)-1 };
enum{ VALUE2 = -1 };
printf( "Is VALUE0 equal to VALUE1? ---> %s", VALUE0 == VALUE1 ? "Yes!" : "No!" );
printf( "Is VALUE0 equal to VALUE2? ---> %s", VALUE0 == VALUE2 ? "Yes!" : "No!" );
打印:
Is VALUE0 equal to VALUE1? ---> No!
Is VALUE0 equal to VALUE2? ---> Yes!
不应该都打印 yes 吗?
我遗漏的 VALUE0 和 VALUE1 的定义之间是否存在差异,也许是类型转换?或者这可能是编译器错误?
在 C 中(与 C++ 不同),枚举常量的类型为 int
。在类型声明结束之前引用枚举常量是合法的。
如果 Keil ARMCC 给你 sizeof(VAL0) != sizeof (int)
,其中 VAL0
是一个枚举常量,那么 Keil ARMCC 就不是一个符合规范的 C 编译器。我在这里看到其他问题表明它不符合要求。
不符合规范不一定是编译器错误(除非供应商声称它符合规范,但据我所知他们没有)。
关于 B 部分:
enum e{
MIN_SIGNED_CHAR_0 = (signed char)( -128 ),
MIN_SIGNED_CHAR_1 = -128,
MIN_SIGNED_CHAR_2 = ( signed int)(signed char)( -128 ),
MIN_SIGNED_CHAR_3 = (unsigned int)(signed char)( -128 ),
MIN_SIGNED_CHAR_0_PLUS_1 = MIN_SIGNED_CHAR_0 + 1,
MIN_SIGNED_CHAR_1_PLUS_1 = MIN_SIGNED_CHAR_1 + 1,
MIN_SIGNED_CHAR_2_PLUS_1 = MIN_SIGNED_CHAR_2 + 1,
MIN_SIGNED_CHAR_3_PLUS_1 = MIN_SIGNED_CHAR_3 + 1,
};
几乎所有符合规范的 C 编译器都应该为 MIN_SIGNED_CHAR_{0,1,2}
常量提供值 -128
(int
类型),为 MIN_SIGNED_CHAR_{0,1,2}_PLUS_1
常量提供值 -127
(也是 int
类型)。唯一可能的摆动空间是使用 SCHAR_MIN == -127
的实现,这是可能的但不太可能,并且显然 而不是 Keil 编译器的情况。如果您得到不同的结果,要么是编译器中的错误。
但是MIN_SIGNED_CHAR_3
的定义是有问题的。 int
值 -128
转换为 signed char
,这不会更改值。然后将其转换为 unsigned int
,得到 UINT_MAX+1-128
(假设 32 位,这是 4294967168
)。指定值超出 int
范围的枚举常量是违反约束的,需要进行诊断。 (你收到编译时警告了吗?)如果编译器不拒绝该程序,结果是未定义的。