Harvester 0 13 ноября, 2019 Опубликовано 13 ноября, 2019 (изменено) · Жалоба Добрый день. Наткнулся вот на такую конструкцию в заголовочном файле (linux): /* Bits to be set in the FLAGS parameter of `timerfd_create'. */ enum { TFD_CLOEXEC = 02000000, #define TFD_CLOEXEC TFD_CLOEXEC TFD_NONBLOCK = 00004000 #define TFD_NONBLOCK TFD_NONBLOCK }; Кто-нибудь может предположить, зачем надо было переопределять элементы перечисления через идентичные define-ы? Изменено 13 ноября, 2019 пользователем Harvester Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 184 13 ноября, 2019 Опубликовано 13 ноября, 2019 · Жалоба 1 час назад, Harvester сказал: Кто-нибудь может предположить, зачем надо было переопределять элементы перечисления через идентичные define-ы? Почему решили что тут что-то "переопределяется"? Имхо: это просто способ зациклить препроцессор в случае если от строки #define TFD_CLOEXEC TFD_CLOEXEC и до строки #undef TFD_CLOEXEC встретится любое выражение, в котором есть TFD_CLOEXEC. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_4afc_ 24 13 ноября, 2019 Опубликовано 13 ноября, 2019 · Жалоба enum для красоты, define чтобы флаги по или складывать Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Harvester 0 13 ноября, 2019 Опубликовано 13 ноября, 2019 (изменено) · Жалоба 27 minutes ago, jcxz said: Почему решили что тут что-то "переопределяется"? Имхо: это просто способ зациклить препроцессор в случае если от строки #define TFD_CLOEXEC TFD_CLOEXEC и до строки #undef TFD_CLOEXEC встретится любое выражение, в котором есть TFD_CLOEXEC. Может я неправильно выразился. Но ведь здесь явно определяется элемент перечисления , а потом с этим же идентификатором написан define. Исходя из логики работы препроцессора все включения TFD_CLOEXEC будут заменены на идентичную строку, что в свою очередь будет обращением к элементу перечисления. Какое-то тройное "масло-масляное" получается :) Потому и вопрос возник - зачем? А Ваше предположение мне кажется неверным. Эти константы используются как битовые параметры, а не как директивы условной компиляции. timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC); И такое объединение enum + define встречается не в одном файле. Кстати, интересный вопрос - можно ли будет обратиться к элементу перечисления TFD_CLOEXEC, после того, как в коде появится #undef TFD_CLOEXEC? 4 minutes ago, _4afc_ said: enum для красоты, define чтобы флаги по или складывать А в чем здесь красота? Дополнительные 5 строк кода, не несущие ни логической, ни пояснительной нагрузки. Изменено 13 ноября, 2019 пользователем Harvester Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_3m 4 13 ноября, 2019 Опубликовано 13 ноября, 2019 · Жалоба 5 минут назад, _4afc_ сказал: enum для красоты, define чтобы флаги по или складывать + чтобы можно было проверить наличие этого enum с помощью #ifdef Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 184 13 ноября, 2019 Опубликовано 13 ноября, 2019 · Жалоба 7 минут назад, Harvester сказал: Исходя из логики работы препроцессора все включения TFD_CLOEXEC будут заменены на идентичную строку, что в свою очередь будет обращением к элементу перечисления. Видимо Вы плохо представляете работу препроцессора. шаг1. Препроцессор ищет в строке известные ему макросы и, если находит в строке известный ему макрос, выполняет текстовую замену имени макроса на его значение, и переходит к шагу2. Если не находит - переходит к шагу3. шаг2. После замены он переходит к шагу1. шаг3. Отдаёт строку компилятору. А "зачем": может быть затем, чтобы данные макросы можно было использовать только в составе аргументов других макросов. Тогда (имхо) не должно быть зацикливания. PS: Всё это имхо, исходя из логики работы препроцессора, не проверял. 10 минут назад, Harvester сказал: Кстати, интересный вопрос - можно ли будет обратиться к элементу перечисления TFD_CLOEXEC, после того, как в коде появится #undef TFD_CLOEXEC? Очевидно, что после #undef в библиотеке имён препроцессора не должно быть более этого имени. Соответственно - он никак не будет реагировать на эту лексему в обрабатываемых строках. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_4afc_ 24 13 ноября, 2019 Опубликовано 13 ноября, 2019 · Жалоба 43 minutes ago, Harvester said: А в чем здесь красота? Дополнительные 5 строк кода, не несущие ни логической, ни пояснительной нагрузки. Говорят дебагеры при использовании enum напишут TFD_CLOEXEC вместо числа. 41 minutes ago, _3m said: + чтобы можно было проверить наличие этого enum с помощью #ifdef Можно попробовать проверить #if Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 13 ноября, 2019 Опубликовано 13 ноября, 2019 · Жалоба Полагаю, что enum для автоматического нумерования констант без пропусков, а #define для возможности делать проверки препроцессором (#ifdef). 5 минут назад, _4afc_ сказал: Можно попробовать проверить #if Не получится. На этапе работы препроцессора зачений еще нет, а #if для имени без значения эквивалентен #if 0 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kabdim 0 13 ноября, 2019 Опубликовано 13 ноября, 2019 · Жалоба Может это потом как-то используется с применением # или ## в макросах? Беглое гугление дает здравое предположение, совпадающее с версией Сергея и 3м. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
xvr 12 13 ноября, 2019 Опубликовано 13 ноября, 2019 · Жалоба возможно ещё в качестве защиты, что бы дальше кто нибудь не написал #define TFD_CLOEXEC чегонибудь На такое компилатор выдаст варнинг (на переопределение дефайна) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 184 13 ноября, 2019 Опубликовано 13 ноября, 2019 · Жалоба Проверил: IAR по-крайней мере имеет видимо какую-то защиту от бесконечной рекурсии при макроподстановке - не зацикливается. Кроме вышеназванных вариантов, такой способ можно ещё использовать для подстановки неких значений вместо элементов списка на этапе компиляции. Например если есть список кодов ошибок и в каких-то местах нужно иметь их коды, а в каких-то строковую расшифровку: #define concatAB_(a, b) a##b #define concatAB(a, b) concatAB_(a, b) #define STR_TFD_CLOEXEC "error 1" #define STR_TFD_NONBLOCK "error 2" enum { TFD_CLOEXEC = 02000000, #define TFD_CLOEXEC TFD_CLOEXEC TFD_NONBLOCK = 00004000 #define TFD_NONBLOCK TFD_NONBLOCK }; ... printf("%08X: %s\n", TFD_CLOEXEC, concatAB(STR_, TFD_CLOEXEC)); printf("%08X: %s\n", TFD_NONBLOCK, concatAB(STR_, TFD_NONBLOCK)); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demiurg_spb 0 14 ноября, 2019 Опубликовано 14 ноября, 2019 · Жалоба Для общего понимания можете почитать это: https://stackoverflow.com/questions/1674032/static-const-vs-define-vs-enum На мой взгляд дефайны нужны только для их последующего использования в препроцессоре (как бы это ни было тавталогично)))). Для склейки, как jcxz показал, для условной компиляции и т.д. и т.п. to: Сергей Борщ #ifdef X ... #endif #if defined(X) && !defined(Y) ... #endif Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 14 ноября, 2019 Опубликовано 14 ноября, 2019 · Жалоба 4 часа назад, demiurg_spb сказал: to: Сергей Борщ Это к чему? Если к моему ответу на "Можно попробовать проверить #if", то я это понял как "#if X == чему-то" (или его частный случай "#if X"), что совсем не то же самое, что и #if defined(X) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GenaSPB 11 14 ноября, 2019 Опубликовано 14 ноября, 2019 (изменено) · Жалоба Про защрту от рекурсии при подстановке которая почему-то оказалась в вашем компиляторе ответ лучше искать в стандарте языка где говорится об правилах работы препроцессора. Изменено 14 ноября, 2019 пользователем GenaSPB Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demiurg_spb 0 22 ноября, 2019 Опубликовано 22 ноября, 2019 · Жалоба On 11/14/2019 at 3:16 PM, Сергей Борщ said: Это к чему? #include <stdio.h> #include <stdlib.h> enum { TFD_CLOEXEC = 02000000 #define TFD_CLOEXEC TFD_CLOEXEC }; int main(void) { unsigned int i=0; #if defined(TFD_CLOEXEC) i |= TFD_CLOEXEC; #endif printf("i= 0x%08x\n", i); return 0; } Я к тому, что это можно использовать таким образом. И более ни к чему) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться