скажите, чем таким положительным отличается
Код: Выделить всё
#define CONST1 1
#define CONST2 2
#define CONST3 3
от
?
как второй вариант облегчает вам жизнь? где тут структуризация, систематизация и т.п. вещи, которые чем-то помогают? разве что у вас IDE с автосворачиванием блоков {} - но извините, это совершенно не то

обычные дефайны, размещенные по логически разделенным заголовочным файлам ничуть не хуже систематизированы
а вот чем хорош мой подход. допустим, я объявил тип
Код: Выделить всё
typedef enum{
KEY_1 = 1,
KEY_2 = 2,
KEY_3 = 3
} KEYCODES;
я планирую использовать переменные и т.п. вещи этого типа для работы с кодами кнопок - это следует из наименования типа. теперь я пишу так
а затем где-то в недрах
Код: Выделить всё
switch(get_key()){
case KEY_1:
// что-то там
break;
case KEY_2:
// другое что-то там
break;
}
и вот тут - СМОТРИТЕ!!! - происходит WARNING компилятора, звучащий в "переводе" так: "
эй, программист! ты в switch-е не все возможные варианты значений функции перебрал!!!" скажите, без использования ТИПА-ПЕРЕЧИСЛЕНИЯ можно получить такое напоминание? согласитесь, что если вы пишите программу, где в перечислении имеется хотя бы десяток вариантов - совсем не лишним будет получить такой варнинг в случае, если что-то забыли, не так ли? аналогичные варнинги я буду получать и с указателями на этот тип, и с параметрами функций и т.п. - все это страхует от ошибок.
самые трудноуловимые ошибки (после работы с НЕТИПИЗОВАННЫМИ указателями) в Си связаны именно с тем фактом, что по стандарту этот язык прощает любые вольности с типами переменных! а мой подход хоть на капельку уменьшает эту неприятность
жалко лишь, что в упомянутой функции ничто не запретит вернуть, например, 12, и никакой варнинг при этом не всплывет

но это Си...
битва с дураками проиграна, победители торжествуют. слава победителям!