type of enumeration constants inside enumerator list in C

时间:2016-04-21 22:43:39

标签: c enums embedded keil

EDITED

I'm currently working on an multi-platform enumeration parser and found this weird behaviour while trying to answer the question above.

Question A)

Does C standard determine the type of the enumeration constants before the enumeration declaration is completed?

For Keil ARMCC, for example:

enum e {
    VAL0 = (signed char)126,
    VAL1,
    VAL2, 
    SIZE0 = sizeof(VAL0), 
    SIZE1 = sizeof(VAL1), 
    SIZE2 = sizeof(VAL2) 
};

I get SIZE0 = 1, SIZE1 = 1, SIZE2 = 8. (if I evaluate the size of the enum constants outside the definition, all have size of int).

Shouldn't they all be equal to sizeof( int )? (Remembering that int, in this case, has size of 4 bytes.)

Question B)

For Keil C251, I have the following:

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!" );

which prints:

Is VALUE0 equal to VALUE1? ---> No!
Is VALUE0 equal to VALUE2? ---> Yes!

Shouldn't both print yes?

is there a difference between the definitions of VALUE0 and VALUE1 that I'm missing, maybe the type cast? Or is this probably a compiler bug?

1 个答案:

答案 0 :(得分:2)

在C中(与C ++不同),枚举常量的类型为int。在类型声明结束之前引用枚举常量是合法的。

如果Keil ARMCC给你sizeof(VAL0) != sizeof (int),其中VAL0是枚举常量,那么Keil ARMCC不是一个符合C的编译器。我在这里看到的其他问题表明它不符合规定。

不符合标准不一定是编译器 bug (除非供应商声称它符合要求,但据我所知,他们不会)。

至于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范围的枚举常量是违反约束,需要诊断。 (您是否收到编译时警告?)如果编译器没有拒绝该程序,结果是未定义的。