Вопрос
Мне любопытно, есть ли какие-либо гарантии того, что константное свертывание выполняется в C.
Где я смотрел
По этой ссылке на сайте, репутация которого мне неизвестна, дается небрежный комментарий:
Все компиляторы C могут сворачивать целочисленные константные выражения, которые присутствуют после раскрытия макросов (требование ANSI C).
Но я ничего не вижу, например. Язык программирования C, второе издание (которое, я полагаю, было тщательно обновлено с учетом всех деталей ANSI C). Но после проверки указателя на наличие ссылок на релевантные слова я не нашел ничего, что обещало бы это. Страницы 38 и 209, в частности, близки, потому что они говорят, что любое выражение, которое может быть вычислено во время компиляции, может использоваться там, где может использоваться константа (возможно, с некоторыми ограничениями, если мы достаточно педантичны). , и в нем говорится, что такие выражения "могут" оцениваться во время компиляции, а не "будут"/(какой-то синоним).
Я искал окончательный проект C89. Слова «folding» и «folded» не дали значимых результатов, а поиск «константное выражение» выдал 63 совпадения, из которых я проверил примерно половину. Основная часть интереса, по-видимому, в основном такая же, как и в книге (в ней используется слово «может» вместо «может», но в данном контексте это синонимы).
Оба из них кажутся мне логически строго подразумевающими, что каждый компилятор ANSI C должен иметь базовые возможности сворачивания констант, но в то же время не существует какого-либо жесткого запрета на компиляцию константных выражений в код, который вычисляет выражение во время выполнения (такая реализация по-прежнему выигрывает от константных выражений, потому что компилятор может генерировать код, который вычисляет его один раз, а затем предполагает, что значение не изменится, и такая реализация может быть вызвана ограничениями в данной базовой архитектуре — например, несколько архитектур RISC должны либо использовать две инструкции для инициализации определенных возможных значений, либо загружать их из ячейки памяти).
Я также бегло просмотрел окончательный черновик C99, но "свернуть" дал один результат не имеет значения, в то время как у "свернутого" и "постоянного" было более сотни совпадений, каждое из которых я в настоящее время не мог выделить время для сканирования.
Мотивация
Я написал эти макросы для большей ясности семантики/намерения в некотором коде с битами:
#define UCHAR_LOW_N_BITS_m(n) (unsigned char )(UCHAR_MAX >> (CHAR_BIT - (n)))
#define UCHAR_NTH_BIT_m(n) (unsigned char )(1 << (n))
..где n
всегда целочисленный литерал. Я хочу успокоиться, услышать успокаивающий голос, говорящий: «Все в порядке, каждый используемый компилятор C, который имеет хоть какое-то значение, свернет эти константы для вас». (PS Я задал отдельный вопрос о том, должен ли UCHAR_NTH_BIT_m
действовать так, как если бы or-one-indexed">биты начинаются с 0-го или 1-го бита, надеюсь, в правильном месте.)
И да, нижний можно превратить в отдельные макросы, например. от #define UCHAR_1ST_BIT_m (unsigned char )1
до #define UCHAR_3RD_BIT_m (unsigned char )4
или столько, сколько мне нужно в коде - и хотя я не решил, какой из них лучше, это, вероятно, спорный вопрос, потому что, если я хочу быть хорошим педантичным-языковым-юристом-типа C программист, я не могу точно избежать верхнего (должен убедиться, что код работает правильно на этих реализациях DSP/встроенных и древних мейнфреймов C).
_m
в нижнем регистре, чтобы сказать, что символ является макросом? Хорошо. - person unwind   schedule 08.04.2016gcc
производят обнадеживающую сборку: они, как правило, утешают компиляторы, выполняя множество оптимизаций, которые не выполнялись более старыми версиями компиляторов, которые некоторые бедолаги все еще могут использовать. - person mtraceur   schedule 08.04.2016_m
, особенно для функциональных макросов. Я меньше люблю символы, написанные заглавными буквами, но иногда использую их для констант, определенных препроцессором. Приведенные примеры являются историческим артефактом: они начинались как несколько простых макросов препроцессора (просто с заглавными буквами), затем я превратил их в макросы, подобные функциям, которые принимали аргументn
. - person mtraceur   schedule 08.04.2016gcc
по умолчанию использовал C89 с расширениями GNU, Visual C Studio по-прежнему не поддерживает некоторые функции C99, о которых я слышал, и я знаю, что существует множество систем, застрявших на старых компиляторах. Поэтому я думаю, что стоит помнить о C89. - person mtraceur   schedule 08.04.2016-std=c11 -pedantic-errors
, и он превратится в компилятор строгого стандарта C. А начиная с GCC 5.x.x, я думаю, по умолчанию используется gnu11, то есть расширения C11 +. Что касается Visual Studio, то это просто кусок дерьма. - person Lundin   schedule 08.04.2016_m
исключенными, и это напомнило мне сделать еще один шаг в оценке недостатков и достоинств моих довольно идиосинкразических привычек именования. - person mtraceur   schedule 08.04.2016