Harvester 0 Posted November 13, 2019 (edited) · Report post Добрый день. Наткнулся вот на такую конструкцию в заголовочном файле (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-ы? Edited November 13, 2019 by Harvester Quote Ответить с цитированием Share this post Link to post Share on other sites
jcxz 0 Posted November 13, 2019 · Report post 1 час назад, Harvester сказал: Кто-нибудь может предположить, зачем надо было переопределять элементы перечисления через идентичные define-ы? Почему решили что тут что-то "переопределяется"? Имхо: это просто способ зациклить препроцессор в случае если от строки #define TFD_CLOEXEC TFD_CLOEXEC и до строки #undef TFD_CLOEXEC встретится любое выражение, в котором есть TFD_CLOEXEC. Quote Ответить с цитированием Share this post Link to post Share on other sites
_4afc_ 0 Posted November 13, 2019 · Report post enum для красоты, define чтобы флаги по или складывать Quote Ответить с цитированием Share this post Link to post Share on other sites
Harvester 0 Posted November 13, 2019 (edited) · Report post 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 строк кода, не несущие ни логической, ни пояснительной нагрузки. Edited November 13, 2019 by Harvester Quote Ответить с цитированием Share this post Link to post Share on other sites
_3m 0 Posted November 13, 2019 · Report post 5 минут назад, _4afc_ сказал: enum для красоты, define чтобы флаги по или складывать + чтобы можно было проверить наличие этого enum с помощью #ifdef Quote Ответить с цитированием Share this post Link to post Share on other sites
jcxz 0 Posted November 13, 2019 · Report post 7 минут назад, Harvester сказал: Исходя из логики работы препроцессора все включения TFD_CLOEXEC будут заменены на идентичную строку, что в свою очередь будет обращением к элементу перечисления. Видимо Вы плохо представляете работу препроцессора. шаг1. Препроцессор ищет в строке известные ему макросы и, если находит в строке известный ему макрос, выполняет текстовую замену имени макроса на его значение, и переходит к шагу2. Если не находит - переходит к шагу3. шаг2. После замены он переходит к шагу1. шаг3. Отдаёт строку компилятору. А "зачем": может быть затем, чтобы данные макросы можно было использовать только в составе аргументов других макросов. Тогда (имхо) не должно быть зацикливания. PS: Всё это имхо, исходя из логики работы препроцессора, не проверял. 10 минут назад, Harvester сказал: Кстати, интересный вопрос - можно ли будет обратиться к элементу перечисления TFD_CLOEXEC, после того, как в коде появится #undef TFD_CLOEXEC? Очевидно, что после #undef в библиотеке имён препроцессора не должно быть более этого имени. Соответственно - он никак не будет реагировать на эту лексему в обрабатываемых строках. Quote Ответить с цитированием Share this post Link to post Share on other sites
_4afc_ 0 Posted November 13, 2019 · Report post 43 minutes ago, Harvester said: А в чем здесь красота? Дополнительные 5 строк кода, не несущие ни логической, ни пояснительной нагрузки. Говорят дебагеры при использовании enum напишут TFD_CLOEXEC вместо числа. 41 minutes ago, _3m said: + чтобы можно было проверить наличие этого enum с помощью #ifdef Можно попробовать проверить #if Quote Ответить с цитированием Share this post Link to post Share on other sites
Сергей Борщ 0 Posted November 13, 2019 · Report post Полагаю, что enum для автоматического нумерования констант без пропусков, а #define для возможности делать проверки препроцессором (#ifdef). 5 минут назад, _4afc_ сказал: Можно попробовать проверить #if Не получится. На этапе работы препроцессора зачений еще нет, а #if для имени без значения эквивалентен #if 0 Quote Ответить с цитированием Share this post Link to post Share on other sites
Kabdim 0 Posted November 13, 2019 · Report post Может это потом как-то используется с применением # или ## в макросах? Беглое гугление дает здравое предположение, совпадающее с версией Сергея и 3м. Quote Ответить с цитированием Share this post Link to post Share on other sites
xvr 0 Posted November 13, 2019 · Report post возможно ещё в качестве защиты, что бы дальше кто нибудь не написал #define TFD_CLOEXEC чегонибудь На такое компилатор выдаст варнинг (на переопределение дефайна) Quote Ответить с цитированием Share this post Link to post Share on other sites
jcxz 0 Posted November 13, 2019 · Report post Проверил: 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)); Quote Ответить с цитированием Share this post Link to post Share on other sites
demiurg_spb 0 Posted November 14, 2019 · Report post Для общего понимания можете почитать это: https://stackoverflow.com/questions/1674032/static-const-vs-define-vs-enum На мой взгляд дефайны нужны только для их последующего использования в препроцессоре (как бы это ни было тавталогично)))). Для склейки, как jcxz показал, для условной компиляции и т.д. и т.п. to: Сергей Борщ #ifdef X ... #endif #if defined(X) && !defined(Y) ... #endif Quote Ответить с цитированием Share this post Link to post Share on other sites
Сергей Борщ 0 Posted November 14, 2019 · Report post 4 часа назад, demiurg_spb сказал: to: Сергей Борщ Это к чему? Если к моему ответу на "Можно попробовать проверить #if", то я это понял как "#if X == чему-то" (или его частный случай "#if X"), что совсем не то же самое, что и #if defined(X) Quote Ответить с цитированием Share this post Link to post Share on other sites
GenaSPB 0 Posted November 14, 2019 (edited) · Report post Про защрту от рекурсии при подстановке которая почему-то оказалась в вашем компиляторе ответ лучше искать в стандарте языка где говорится об правилах работы препроцессора. Edited November 14, 2019 by GenaSPB Quote Ответить с цитированием Share this post Link to post Share on other sites
demiurg_spb 0 Posted November 22, 2019 · Report post 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; } Я к тому, что это можно использовать таким образом. И более ни к чему) Quote Ответить с цитированием Share this post Link to post Share on other sites