Programming in C

Enums

Gerald Senarclens de Grancy

What is an enum?

An enum is a type for limiting variables to be one of a set of named constants

  • Values are called elements, members, or enumerators of the type
  • Enumerators are identifiers that behave as constants
enum Name {
  first_choice = <integral constant>,  // assignment is optional; default is 0
  second_choice,  // value is previous value + 1
  ...
  nth_choice,
};
enum Name variable = second_choice;

Purpose of Enums

Improve Readability

Enums can replace "magic numbers" with meaningful names

Example: Without Enums

// ... using magic constants





// imagine a network request
int status = get(url, buffer);
if (status == 200) {  // What is 200??
  // ...
} else if (status == 404) {  // 404??
  // ...
}

Example: Using Enums

// ...
enum Status {
  SUCCESS = 200,
  NOT_FOUND = 404
};

// imagine a network request
enum Status status = get(url, buffer);
if (status == SUCCESS) {
  // ...
} else if (status == NOT_FOUND) {
  // ...
}

Purpose of Enums

Automatically Create "Unique" Values

Values underlying an enum are automatically created if not assigned

enum Orientation {
  NORTH,  // 0
  EAST,  // 1
  SOUTH,
  WEST,
};

Better Maintainability

Changing values of these constants is done in a single location

Which Problems can Enums Cause?

No Scoping

Enum constants are not scoped by their enclosing enum block

enum Orientation { NORTH, EAST, SOUTH, WEST, };
// ...
const uint32_t NORTH = 0;  // compiler error: namespace is "polluted"

Misleading Implicit Conversion to int

enum Orientation direction = EAST;  // intention is clear
int choice = EAST;  // much harder to understand intention later on

Compilers Allow Reusing Values

#include <stdio.h>


enum Color {
  RED = 5,
  GREEN,
  BLUE = 5,  // outch
};

int main() {
  if (RED == BLUE) {  // valid (an no compiler warning about this)
    puts("what a mess");
  }
  return 0;
}

Visualize execution

Comparison of Unrelated enum Constants

#include <stdio.h>


enum Color { RED, GREEN, BLUE, };
enum Orientation { NORTH, EAST, SOUTH, WEST, };

int main() {
  if (RED == NORTH) {  // valid (at least, decent compilers warn about this)
    printf("what a mess\n");
  }
  return 0;
}

Visualize execution

Implicit Conversion From int

#include <stdio.h>

int main() {
  enum Color { RED, GREEN, BLUE };
  enum Color my_color = 1;  // Valid in C!  my_color is GREEN
  int color_int = my_color;  // Implicit conversion
  my_color = color_int + 10;  // Also valid for compiler! 💀
  printf("my_color: %d\n", my_color);  // definitely no color 💩
  return 0;
}

Visualize execution

Example: Working With Enums

It is common to use switch when working with an enum

#include <stdio.h>

enum Orientation {
  NORTH,
  EAST,
  SOUTH,
  WEST,
};


int main() {
  enum Orientation heading = EAST;  // user controls movement of character
  switch (heading) {
  case NORTH:
    puts("Hero moves north...");  // in lieu of proper action
    break;
  case EAST:
    puts("Hero moves east...");
    break;
  case SOUTH:
    puts("Hero moves south...");
    break;
  case WEST:
    puts("Hero moves west...");
    break;
  }
  return 0;
}

Visualize execution

Questions
and feedback...