与枚举器同名的变量

Variable named the same as enumerator

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

#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 标准,这是什么定义的行为,或者这是未定义的行为?无论它是否被定义,我猜这种类型的例子至少是由于歧义而导致的不好的做法。

谢谢!

我预计 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表示局部变量,不是枚举常量。用自身初始化变量并不能真正初始化变量;它将未定义的垃圾复制到值中。

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

  1. ... If an identifier designates two different entities in the same name space, the scopes might overlap. If so, the scope of one entity (the inner scope) will end strictly before the scope of the other entity (the outer scope). Within the inner scope, the identifier designates the entity declared in the inner scope; the entity declared in the outer scope is hidden (and not visible) within the inner scope.

7 Structure, union, and enumeration tags have scope that begins just after the appearance of the tag in a type specifier that declares the tag. Each enumeration constant has scope that begins just after the appearance of its defining enumerator in an enumerator list. Any other identifier has scope that begins just after the completion of its declarator

所以在这个声明中

TEST_ENUM ENUM_VAL_1 = ENUM_VAL_1;

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

其实是自己初始化的,值不确定

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

1 The point of declaration for a name is immediately after its complete declarator (Clause 8) and before its initializer (if any), except as noted below. [ Example:

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

Here the second x is initialized with its own (indeterminate) value. —end example ]