Реализация типа данных диапазона

У меня есть устаревший код, который использует enum в качестве диапазона и выполняет итерацию по диапазону. Мне нужно перенести это на новую платформу и сделать его безопаснее.

Примечание. enums небезопасно перебирать, поскольку между значениями могут быть "дыры" или промежутки.

Я ищу безопасный шаблон языка C для типа диапазона.

Например, учитывая диапазон (КРАСНЫЙ, ФИОЛЕТОВЫЙ, СИНИЙ, ЗЕЛЕНЫЙ, ЖЕЛТЫЙ, ОРАНЖЕВЫЙ), я хочу перебирать каждое значение, например «ДЛЯ цвета В (КРАСНЫЙ, ФИОЛЕТОВЫЙ, СИНИЙ, ЗЕЛЕНЫЙ, ЖЕЛТЫЙ, ОРАНЖЕВЫЙ)».

При поиске в SO и в Интернете я получаю ответы о диапазоне типа данных, например о диапазоне целых чисел.

Этот код будет находиться во встроенной системе, использующей процессор ARM7.


person Thomas Matthews    schedule 05.01.2012    source источник
comment
Могут ли по умолчанию быть пробелы? Вы всегда можете указать значения перечислений, например enum { zero = 0, one = 1, two = 2};, не так ли?   -  person Dan Fego    schedule 05.01.2012
comment
Проблема в том, что когда кто-то вставляет четыре = 4 в enum, это приводит к неопределенному поведению (или трудно найти ошибки).   -  person Thomas Matthews    schedule 05.01.2012


Ответы (2)


Перечисление может работать нормально, если вы позволяете компилятору выбирать значения. Так не было бы дыр. Вы можете, например, сделать это:

enum colors {
    FIRST_COLOR=0,
    RED=FIRST_COLOR, VIOLET, BLUE, GREEN, YELLOW, ORANGE,
    NUM_COLORS
}

enum colors color;
for (color=FIRST_COLOR; color<NUM_COLORS; color++) {
    // whatever
}

И цитата из стандарта ANSI C:

Если первый перечислитель не имеет =, значение его константы перечисления равно 0. Каждый последующий перечислитель с no = определяет свою константу перечисления как значение константного выражения, полученного добавлением 1 к значению предыдущей константы перечисления.

person ugoren    schedule 05.01.2012
comment
Мой компилятор, IAR, дает мне перечислимый тип, смешанный с другим типом для for (color = 0; color < ORANGE; color++), но я предполагаю, что это из-за 0. - person Thomas Matthews; 05.01.2012
comment
Я использую gcc, где перечисления и целые числа можно свободно смешивать. Я действительно хотел бы, чтобы он предупреждал о таких смесях. Я думаю, что использование FIRST_COLOR должно удовлетворить любой компилятор. - person ugoren; 05.01.2012
comment
Мне очень нравится трюк FIRST_COLOR. Это делает итерационные циклы более удобочитаемыми и менее подверженными авариям при изменении списка перечислений. - person Thomas Matthews; 06.01.2012

Вы можете использовать массив:

 static Color colors[] = {Red, Violet, Green, Yellow, Orange};
 #define SIZE(x) sizeof(x)/sizeof(*x)

 for(x=0; x<SIZE(colors); x++){
      //do stuff with colors[x]
 }

В противном случае вы видите обычный паттерн:

 enum Colors {FirstColor, Red=0, Violet, Green, Yellow, Orange, LastColor};

 for(x=FirstColor; x<LastColor; x++){
     //do stuff with x.
 }

Но если способ их итерации изменится, вы всегда можете определить функцию nextcolor() и:

 for(x=FirstColor;x<LastColor;x=nextcolor(x)){
     //do stuff with x.
 }
person Dave    schedule 05.01.2012