[C] В чём маза #define A A ?
---
...Я работаю антинаучным аферистом...
#define _MY_TYPE_DEFINED_
enum MyType {
A = 1,
#define A A
B = 2,
#define B B
C = 3,
#define C C
D = 4,
#define D D
...
};
....
#ifdef _MY_TYPE_DEFINED_
...
#endif
сравни с _SIZE_T_DEFINED, _WCHAR_T_DEFINED, _FILE_DEFINED и т.п. (я смотрю в stdio.h от MSVC 6.0 [cl v12.00.8168, от 1998 года] )
Зачем переопределять константы enum-ов?
а в каком файле ты такое встречаешь? Может быть, енум в разных версиях может содержать разные значения, и хочется иметь по дефайну на каждое?
/usr/include/bits/confname.h
ну и т.д. почти все файлы в каталоге bits
как оно может быть разное, если явно указано его значение?
enum
{
FE_INVALID = 0x01,
#define FE_INVALID FE_INVALID
__FE_DENORM = 0x02,
FE_DIVBYZERO = 0x04,
#define FE_DIVBYZERO FE_DIVBYZERO
FE_OVERFLOW = 0x08,
#define FE_OVERFLOW FE_OVERFLOW
FE_UNDERFLOW = 0x10,
#define FE_UNDERFLOW FE_UNDERFLOW
FE_INEXACT = 0x20
#define FE_INEXACT FE_INEXACT
};
Просто, может быть, пользователь может подгружать разные версии хедеров. И не хочет разбираться, что данный конкретный хедер объявляет, а что нет. Захочет воспользоваться А, проверит, определено ли такое значение, и если да - воспользуется им.
Это, конечно, только предположение.
о! кажися я понял.
наводит на некоторые подозрения следующая конструкция:
#define FE_ALL_EXCEPT (FE_INEXACT | FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID)
Если эти константы определить через макросы имхо есть вероятность что препроцессор их "вычислит" на этапе препроцессирования. хотя врядли. он же значения их не знает.
в общем, хрен знает.
как нашёл: у меня мой препроцессор запнулся на этом месте
/* Standard streams. */
extern FILE *stdin; /* Standard input stream. */
extern FILE *stdout; /* Standard output stream. */
extern FILE *stderr; /* Standard error output stream. */
/* C89/C99 say they're macros. Make them happy. */
#define stdin stdin
#define stdout stdout
#define stderr stderr
но для нестандартизованных вещей - нафига?
А что это за стдио.х такой? У меня в MSVC таких строчек нет
т.е. раньше было
#define A 1
#define B 2
#define C 3
#define D 4
Сейчас этот же код написали более чисто, через enum, но для совместимости также оставили и define-ы.
2kaifa: я тот код вижу у себя в /usr/include/stdio.h
стандартизован в данном случае /usr/include/fenv.h
чего нельзя сказать, например про resource.h
Я пока вижу только одно: в #ifdef или #ifndef.
Ну, ещё переопределения через тот же препроцессор.
---
...Я работаю антинаучным аферистом...
> Ну, ещё переопределения через
Именно для этого.
Это же библиотечные файлы, поэтому их стараются менять так, чтобы новая версия была максимально совместима с предыдущими.
---
...Я работаю антинаучным аферистом...
но может быть как раз ifdef используется, что-нибудь типа такого в самой проге:
#ifndef A
#define A 1
#endif
транслятор должен выдать сообщение об ошибке?
Или зачем дублирование кода?
---
...Я работаю антинаучным аферистом...
> транслятор должен выдать сообщение об ошибке?
дык, цель написания программы не в том, чтобы компилятор выдал ошибки, если что-то не так, а в том, чтобы программа работала, а перед этим корректно компилировалась.
> Или зачем дублирование кода?
Потому что опять же, например, в самой древней библиотеке этих констант вообще не было, поэтому их приходилось определять в самой проге.
если ожидаешь выполнение той же работы на уровне программирования.
В старых программах же не писалось "А?"
Там, скорее всего, писали просто 1.
И уж тем более не "#ifndef".
---
...Я работаю антинаучным аферистом...
2. Старый код рассчитывает на то, что в библиотеке будут #define-ы
3. Но новый код удобнее писать без #define-ов, удобнее когда те же константы объявлены, как enum
Соответственно, вывод:
библиотека должна поддерживать и #define-ы, и enum
Может, стоило бы разделить библиотеку на три части?
---
...Я работаю антинаучным аферистом...
И как бы выглядел процесс подключения этих частей? И что полезного дало бы такое разделение?
2. Старый код рассчитывает на то, что в библиотеке будут #define-ыПриведи пример кода, который соберется с константой объявленной через define, но не соберется с константной реализованной через enum. "ifdef A" не использовать.
3. Но новый код удобнее писать без #define-ов, удобнее когда те же константы объявлены, как enum
Сначала ты сам вводишь ограничение, а потом просишь его обойти.
ps
Почему ты считаешь, что старый код не использовал #ifdef?
Не следует использовать ifdef для тех констант, которые определяют числовое значение, а не поддержку какой-то фичи.
Оно дало бы куда более читаемый код
Со всеми вытекающими.
---
...Я работаю антинаучным аферистом...
ps
В рассматриваемой задаче есть три субъекта, у каждого из субъектов свои цели:
1. Автор библиотеки. Цель: упростить пользование данной библиотекой.
2. Автор legacy-кода. Цель: воспользоваться усовершенствованной библиотекой, с как можно меньшим изменением собственного кода
3. Автор нового кода. Писать кода, используя самые удобные и эффективные средства (best practices) на данный момент.
Можно заметить, что оригинальное решение автора библиотеки обеспечивало наилучшее достижение целей всех трех субъектов.
Твое же предложение осложняет жизнь всем трех субъектам, не давая ничего взамен.
Зачем тогда использовать твое решение? Побыть мазохистом?
Особенно в тех случаях, когда изменения касаются нескольких
строк.
В конце концов, "природа не храм, а мастерская."
Довольно часто имеет смысл воспользоваться только небольшой
частью библиотеки, и вот тогда начинается весёлая жизнь.
Сможешь объяснить, на кой чёрт нужны исходники, если проще будет
написать всё сызнова, чем выдрать готовое.
---
...Я работаю антинаучным аферистом...
Нужно учиться не бояться изменять код.
Автор стандартных хедеров не имеет право совать свой нос в такие вопросы. Существуют гиганские проекты, программисты которых уже все, например, умерли. И никто не собирается разбираться, на что в них нужно заменить
#ifdef A
...
#endif
И уж тем более отлаживать, если заменил на что-то неподходящее!..
Не следует использовать ifdef для тех констант, которые определяют числовое значение
Почему это?
Есть функция f(int и этот int задает код операции. Возможны операции OPERATION_1, OPERATION_2, ... OPERATION_100. Это define-ы. Я пишу
#ifdef OPERATION_58
//Функция может выполнить операцию 58
f(OPERATION_58);
#else
//Не может (старая версия библиотеки, или еще чего?).
//Достигаем той же функциональности как-то еще
f(OPERATION_24);
f(OPERATION_37);
do_somthing_else;
#endif
PS И еще раз повторю - не автор библиотеки должен решать
следует использовать ifdef для тех констант, которые
или нет...
Оставить комментарий
yolki
Во некоторых .h файлах довольно часто встерчается такое:В чём потусторонний смысл определять такой макрос?