变量名称与枚举器相同

时间:2015-01-07 20:00:44

标签: c enums standards

以下内容的定义行为是什么?

#include <stdio.h>

typedef enum {
  ENUM_VAL_1 = 1,
  ENUM_VAL_2 = 2
} TEST_ENUM;

int main() {
  TEST_ENUM testVar1 = ENUM_VAL_1;
  TEST_ENUM ENUM_VAL_1 = ENUM_VAL_1;
  TEST_ENUM testVar2 = ENUM_VAL_1;

  printf("ENUM_VAL_1 = %u\n",ENUM_VAL_1);
  printf("testVar1 = %u\n",testVar1);
  printf("testVar2 = %u\n",testVar2);

  return 0;
}

从我对GCC和MSVC编译器的测试中,这样做的行为是testVar1将被设置为等于枚举值“ENUM_VAL_1”或1.但是,下一个语句将尝试将变量ENUM_VAL_1设置为等于它自己的值,当然是未初始化的,因此是垃圾,而不是将变量ENUM_VAL_1设置为等于枚举值ENUM_VAL_1。然后,当然,testVar2也将获得与变量ENUM_VAL_1相同的垃圾值。

根据C标准定义的行为是什么,还是这种未定义的行为?不管它是否被定义,我猜这种类型的例子至少是不好的做法,因为它含糊不清。

谢谢!

2 个答案:

答案 0 :(得分:6)

根据C标准(6.2.1标识符范围)

  
      
  1. ...如果标识符指定同一名称空间中的两个不同实体,则范围可能会重叠。如果是这样,一个实体的范围   (内部范围)将严格地在另一方的范围之前结束   实体(外部范围)。 在内部范围内,标识符   指定在内部范围内声明的实体;宣布的实体   在外部范围内隐藏(并且不可见)在内部   范围。
  2.   

  

7结构,联合和枚举标记的范围从一开始就是   在声明了的类型说明符中出现标记之后   标签。每个枚举常量的范围都在此之后开始   枚举器列表中定义的枚举器的外观。的不限   其他标识符具有在完成后立即开始的范围   其声明者

所以在这个宣言中

TEST_ENUM ENUM_VAL_1 = ENUM_VAL_1;

声明符ENUM_VAL_1在sign =之前被视为已完成。所以它隐藏了枚举器。

实际上它是自己初始化的,并且具有不确定的值。

同样适用于C ++(3.3.2声明点)

  

1名称的声明点紧随其后   完整的声明者(第8条)和初始化者(如果有的话),   除非如下所述。 [例如:

int x = 12;
{ int x = x; }
  

这里第二个x用它自己的(不确定的)值初始化。    - 例子]

答案 1 :(得分:3)

我预计TEST_ENUM ENUM_VAL_1 = ENUM_VAL_1;行无法编译,但确实如此。我将分配的值更改为ENUM_VAL_2,然后打印得到ENUM_VAL_1 = 2testVar1 = 1testVar2 = 2,因此ENUM_VAL_1是一个局部变量。

这实际上是一个例行的范围界定问题;这意味着main()中的变量声明会将声明置于外部 - 如果typedefmain()之内,则代码将无法编译。将-Wshadow添加到编辑选项以查看阴影。设置testVar1后,ENUM_VAL_1表示局部变量,而不是枚举常量。用自己初始化变量并不能真正初始化变量;它将未定义的垃圾复制到值中。