В препроцессоре C#define включает предыдущие #define?

С этими #defineс без аргументов

#define r 31
#define UMASK (0xffffffffUL<<r)
#define LMASK (0xffffffffUL ^ UMASK)

будет ли UMASK идентичен (0xffffffffUL<<31) и LMASK идентично (0xffffffffUL ^ (0xffffffffUL<<31)) в реальном коде? Который

uint32_t x = (state_array[k] & UMASK) | (state_array[j] & LMASK);

Я хочу, чтобы компилятор видел это как

uint32_t x = (state_array[k] & 0x80000000UL) | (state_array[j] & 0x7fffffffUL);

Я просто не могу расшифровать стандарт настолько, чтобы его объяснить.

см. godbolt.org/z/7EMff3hEb. Это использование шаблона препроцессора.

danblack 04.06.2024 06:05

Я это уже сделал и вроде компилируется правильно. Но я как-то не доверяю этому. Но по «образовательным» причинам (пример кода в Википедии) я хотел использовать эти #define вместо явных масок.

robert bristow-johnson 04.06.2024 06:10

«Я просто не могу расшифровать стандарт настолько, чтобы его объяснить». Если вы используете gcc, вы можете использовать параметр командной строки -E для создания выходных данных препроцессора вместо компиляции кода. Затем вы можете проверить, как выглядит ваш код после замены макросов. Это не совсем то же самое, что изучение стандарта, но вполне подходит для большинства ситуаций.

Gerhardh 04.06.2024 08:10
0xffffffffUL << 31 довольно бессмысленно. Просто напишите 1UL << 31.
Lundin 05.06.2024 12:31

Что, если r не 31? Цель маски — разделить биты слова на две части. Вот контекст.

robert bristow-johnson 05.06.2024 17:18
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
5
93
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

будет UMASK идентично (0xffffffffUL<<31)

Да.

и LMASK быть идентичным (0xffffffffUL ^ (0xffffffffUL<<31))

Да.

При сканировании текста замены макроса для UMASK токен r будет распознан как макрос и 31 будет скопирован, поэтому следует результат UMASK.

При сканировании текста замены макроса для LMASK токен UMASK будет распознан как макрос и расширен, как и раньше, поэтому следует результат LMASK.

Стандарт C11 §6.10.3 Замена макросов ¶9 определяет расширение объектно-подобных макросов:

Директива предварительной обработки формы

# define identifier replacement-list new-line

определяет объектноподобный макрос, который приводит к замене каждого последующего экземпляра имени макроса списком замен токенов предварительной обработки, которые составляют остальную часть директивы. Затем список замены повторно просматривается для поиска дополнительных имен макросов, как указано ниже.

171)

§6.10.3.4 Повторное сканирование и дальнейшая замена подробно описывает сканирование, происходящее при обработке текста замены.

После замены всех параметров в списке замены и выполнения обработки # и ## все токены предварительной обработки меток места удаляются. Полученная последовательность токенов предварительной обработки затем повторно сканируется вместе со всеми последующими токенами предварительной обработки исходного файла для замены новых имен макросов.

Если имя заменяемого макроса обнаружено во время сканирования списка замены (не включая остальные токены предварительной обработки исходного файла), оно не заменяется. Более того, если при каких-либо вложенных заменах встречается имя заменяемого макроса, оно не заменяется. Эти незаменяемые токены предварительной обработки имени макроса больше не доступны для дальнейшей замены, даже если они позже (повторно) проверяются в контекстах, в которых этот токен предварительной обработки имени макроса в противном случае был бы заменен.

Результирующая полностью замененная макросом последовательность токенов предварительной обработки не обрабатывается как директива предварительной обработки, даже если она похожа на нее, но все выражения прагматических унарных операторов внутри нее затем обрабатываются, как указано в разделе 6.10.9 ниже.

спасибо за подтверждение того, что уже сказал компилятор, просто я беспокоюсь. Я написал рабочий код C для ГПСЧ Mersenne Twister и поместил его в Википедию. Я хотел, чтобы он отражал текст и символы, использованные в основной части статьи, но создать битовые маски с помощью краткого кода было немного сложно. - - - - - - 745 тыс. реп. блин.

robert bristow-johnson 04.06.2024 17:37

Другие вопросы по теме