以下内容的定义行为是什么?
#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标准定义的行为是什么,还是这种未定义的行为?不管它是否被定义,我猜这种类型的例子至少是不好的做法,因为它含糊不清。
谢谢!
答案 0 :(得分:6)
根据C标准(6.2.1标识符范围)
- ...如果标识符指定同一名称空间中的两个不同实体,则范围可能会重叠。如果是这样,一个实体的范围 (内部范围)将严格地在另一方的范围之前结束 实体(外部范围)。 在内部范围内,标识符 指定在内部范围内声明的实体;宣布的实体 在外部范围内隐藏(并且不可见)在内部 范围。强>
醇>
和
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 = 2
,testVar1 = 1
和testVar2 = 2
,因此ENUM_VAL_1
是一个局部变量。
这实际上是一个例行的范围界定问题;这意味着main()
中的变量声明会将声明置于外部 - 如果typedef
在main()
之内,则代码将无法编译。将-Wshadow
添加到编辑选项以查看阴影。设置testVar1
后,ENUM_VAL_1
表示局部变量,而不是枚举常量。用自己初始化变量并不能真正初始化变量;它将未定义的垃圾复制到值中。