[C] В чём маза #define A A ?

yolki

Во некоторых .h файлах довольно часто встерчается такое:


enum {
A = 1,
#define A A
B = 2,
#define B B
C = 3,
#define C C
D = 4,
#define D D
...
};


В чём потусторонний смысл определять такой макрос?

Ivan8209

Наверное, в том, что #ifdef начнёт работать.
---
...Я работаю антинаучным аферистом...

yolki

для таких случаев пишут так:


#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-ов?

maggi14

а в каком файле ты такое встречаешь? Может быть, енум в разных версиях может содержать разные значения, и хочется иметь по дефайну на каждое?

yolki

/usr/include/bits/fenv.h
/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
};

maggi14

Что за файлы, я, честно говоря, не знаю. В Юниксах я лох.
Просто, может быть, пользователь может подгружать разные версии хедеров. И не хочет разбираться, что данный конкретный хедер объявляет, а что нет. Захочет воспользоваться А, проверит, определено ли такое значение, и если да - воспользуется им.
Это, конечно, только предположение.

yolki

как я уже сказал - логичнее было бы делать макрос *_DEFINED, как у FILE, wchar_t и т.п.
о! кажися я понял.
наводит на некоторые подозрения следующая конструкция:

#define FE_ALL_EXCEPT (FE_INEXACT | FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID)


Если эти константы определить через макросы имхо есть вероятность что препроцессор их "вычислит" на этапе препроцессирования. хотя врядли. он же значения их не знает.
в общем, хрен знает.
как нашёл: у меня мой препроцессор запнулся на этом месте

Chupa

stdio.h:


/* 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

yolki

возможно. для stdin/stdout/getc и кое-чего ещё я могу это понять.
но для нестандартизованных вещей - нафига?

maggi14


А что это за стдио.х такой? У меня в MSVC таких строчек нет

Dasar

Есть идея, что для совместимости.
т.е. раньше было


#define A 1
#define B 2
#define C 3
#define D 4


Сейчас этот же код написали более чисто, через enum, но для совместимости также оставили и define-ы.

yolki

о! это разумно.
2kaifa: я тот код вижу у себя в /usr/include/stdio.h

Chupa

стандартизован в данном случае /usr/include/fenv.h

yolki

ок, fenv.h - стандартизован. просто плохой пример.
чего нельзя сказать, например про resource.h

Ivan8209

Можешь пояснить, в чём заключается совместимость?
Я пока вижу только одно: в #ifdef или #ifndef.
Ну, ещё переопределения через тот же препроцессор.
---
...Я работаю антинаучным аферистом...

Dasar

> Я пока вижу только одно: в #ifdef или #ifndef.
> Ну, ещё переопределения через
Именно для этого.
Это же библиотечные файлы, поэтому их стараются менять так, чтобы новая версия была максимально совместима с предыдущими.

Ivan8209

А где-нибудь это используется?
---
...Я работаю антинаучным аферистом...

Dasar

хз
но может быть как раз ifdef используется, что-нибудь типа такого в самой проге:


#ifndef A
#define A 1
#endif

Ivan8209

А зачем такое делать, если в случае ссылки на неопределённое "А,"
транслятор должен выдать сообщение об ошибке?
Или зачем дублирование кода?
---
...Я работаю антинаучным аферистом...

Dasar

> А зачем такое делать, если в случае ссылки на неопределённое "А,"
> транслятор должен выдать сообщение об ошибке?
дык, цель написания программы не в том, чтобы компилятор выдал ошибки, если что-то не так, а в том, чтобы программа работала, а перед этим корректно компилировалась.
> Или зачем дублирование кода?
Потому что опять же, например, в самой древней библиотеке этих констант вообще не было, поэтому их приходилось определять в самой проге.

Ivan8209

Зачем тогда писать усовершенствованную библиотеку,
если ожидаешь выполнение той же работы на уровне программирования.
В старых программах же не писалось "А?"
Там, скорее всего, писали просто 1.
И уж тем более не "#ifndef".
---
...Я работаю антинаучным аферистом...

Dasar

1. Библиотеки расчитаны на работу и со старым и с новым кодом.
2. Старый код рассчитывает на то, что в библиотеке будут #define-ы
3. Но новый код удобнее писать без #define-ов, удобнее когда те же константы объявлены, как enum
Соответственно, вывод:
библиотека должна поддерживать и #define-ы, и enum

Ivan8209

Как насчёт модульности?
Может, стоило бы разделить библиотеку на три части?
---
...Я работаю антинаучным аферистом...

Dasar

> Может, стоило бы разделить библиотеку на три части?
И как бы выглядел процесс подключения этих частей? И что полезного дало бы такое разделение?

sergey_m

2. Старый код рассчитывает на то, что в библиотеке будут #define-ы
3. Но новый код удобнее писать без #define-ов, удобнее когда те же константы объявлены, как enum
Приведи пример кода, который соберется с константой объявленной через define, но не соберется с константной реализованной через enum. "ifdef A" не использовать.

Dasar

> "ifdef A" не использовать.
Сначала ты сам вводишь ограничение, а потом просишь его обойти.
ps
Почему ты считаешь, что старый код не использовал #ifdef?

sergey_m

Не следует использовать ifdef для тех констант, которые определяют числовое значение, а не поддержку какой-то фичи.

Ivan8209

#include <this-damn-library-X.X.h>
Оно дало бы куда более читаемый код
Со всеми вытекающими.
---
...Я работаю антинаучным аферистом...

Dasar

Такое название напрягло бы пользователей указанной библиотеке.
ps
В рассматриваемой задаче есть три субъекта, у каждого из субъектов свои цели:
1. Автор библиотеки. Цель: упростить пользование данной библиотекой.
2. Автор legacy-кода. Цель: воспользоваться усовершенствованной библиотекой, с как можно меньшим изменением собственного кода
3. Автор нового кода. Писать кода, используя самые удобные и эффективные средства (best practices) на данный момент.
Можно заметить, что оригинальное решение автора библиотеки обеспечивало наилучшее достижение целей всех трех субъектов.
Твое же предложение осложняет жизнь всем трех субъектам, не давая ничего взамен.
Зачем тогда использовать твое решение? Побыть мазохистом?

Ivan8209

Нужно учиться не бояться изменять код.
Особенно в тех случаях, когда изменения касаются нескольких
строк.
В конце концов, "природа не храм, а мастерская."
Довольно часто имеет смысл воспользоваться только небольшой
частью библиотеки, и вот тогда начинается весёлая жизнь.
Сможешь объяснить, на кой чёрт нужны исходники, если проще будет
написать всё сызнова, чем выдрать готовое.
---
...Я работаю антинаучным аферистом...

rosali

Нужно учиться не бояться изменять код.

Автор стандартных хедеров не имеет право совать свой нос в такие вопросы. Существуют гиганские проекты, программисты которых уже все, например, умерли. И никто не собирается разбираться, на что в них нужно заменить
#ifdef A
...
#endif
И уж тем более отлаживать, если заменил на что-то неподходящее!..

rosali

Не следует использовать 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 для тех констант, которые

или нет...
Оставить комментарий
Имя или ник:
Комментарий: