С этими #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);
Я просто не могу расшифровать стандарт настолько, чтобы его объяснить.
Я это уже сделал и вроде компилируется правильно. Но я как-то не доверяю этому. Но по «образовательным» причинам (пример кода в Википедии) я хотел использовать эти #define
вместо явных масок.
«Я просто не могу расшифровать стандарт настолько, чтобы его объяснить». Если вы используете gcc, вы можете использовать параметр командной строки -E
для создания выходных данных препроцессора вместо компиляции кода. Затем вы можете проверить, как выглядит ваш код после замены макросов. Это не совсем то же самое, что изучение стандарта, но вполне подходит для большинства ситуаций.
0xffffffffUL << 31
довольно бессмысленно. Просто напишите 1UL << 31
.
Что, если r
не 31? Цель маски — разделить биты слова на две части. Вот контекст.
будет
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 тыс. реп. блин.
см. godbolt.org/z/7EMff3hEb. Это использование шаблона препроцессора.