Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Variable named the same as enumerator

Tags:

c

enums

standards

What is the defined behavior for something like the following?

#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;
}

From my testing with both GCC and MSVC compilers, the behavior of this is that testVar1 will be set equal to the enumeration value "ENUM_VAL_1" or 1. However, the next statement will try to set the variable ENUM_VAL_1 equal to its own value, which is of course current uninitialized and thus garbage, instead of setting the variable ENUM_VAL_1 equal to the enumeration value ENUM_VAL_1. Then, of course, testVar2 will also get the same garbage value as the variable ENUM_VAL_1.

What is the defined behavior of this according to the C standards, or is this undefined behavior? Whether or not it is defined, I'm guessing this type of example is bad practice at very least due to the ambiguity.

Thanks!

like image 909
Bryan Henry Avatar asked Jan 07 '15 20:01

Bryan Henry


People also ask

How to create enumerated type variables in Java?

It can be created in two types:- It can be declared during declaring enumerated types, just add the name of the variable before the semicolon.or, Beside this, we can create enumerated type variables as same as the normal variables. By default, the starting code value of the first element of enum is 0 (as in the case of array) .

What is enumerator in C++?

Enumerator types of values are also known as enumerators. It is also assigned by zero the same as the array. It can also be used with switch statements. For example: If a gender variable is created with value male or female.

Can two enum names have the same value?

1 Two enum names can have same value. For example, in the following C program both ‘Failed’ and ‘Freezed’ have same value 0. ... 2 If we do not explicitly assign values to enum names, the compiler by default assigns values starting from 0. ... 3 We can assign values to some name in any order. ... More items...

What are the values of constants and enum variables?

By default, the values // of the constants are as follows: // constant1 = 0, constant2 = 1, constant3 = 2 and // so on. enum flag {constant1, constant2, constant3, ....... }; Variables of type enum can also be defined. They can be defined in two ways:


2 Answers

According to the C Standard (6.2.1 Scopes of identifiers)

  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.

And

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

So in this declaration

TEST_ENUM ENUM_VAL_1 = ENUM_VAL_1;

declarator ENUM_VAL_1 is considered completed before the sign =. So it hides the enumerator.

In fact it is initialized by itself and has an indeterminate value.

The same is valid for C++ (3.3.2 Point of declaration)

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 ]

like image 71
Vlad from Moscow Avatar answered Sep 18 '22 11:09

Vlad from Moscow


I expected the TEST_ENUM ENUM_VAL_1 = ENUM_VAL_1; line to fail to compile, but it does. I changed the assigned value to ENUM_VAL_2, and the printing then gives ENUM_VAL_1 = 2, testVar1 = 1 and testVar2 = 2, so ENUM_VAL_1 is a local variable.

It is actually a routine scoping issue; it means that the variable declaration in main() shadows the declaration outside — and if the typedef were within main(), the code would not compile. Add -Wshadow to your compilation options to see the shadowing. After setting testVar1, ENUM_VAL_1 means the local variable, not the enumeration constant. Initializing a variable with itself doesn't really initialize the variable; it copies undefined garbage into the value.

like image 20
Jonathan Leffler Avatar answered Sep 22 '22 11:09

Jonathan Leffler