2016-04-08 8 views
3

Вопрос

Мне интересно, если есть какие-либо гарантии о постоянном складывания делается в С.Минимальная гарантированная постоянная складывая в C

Где я смотрел

This link на сайте которого респектабельности является неизвестно мне делает оффициальный комментарий:

Все компиляторы C могут складывать целочисленные константные выражения, которые присутствуют после макрорасширения (требование ANSI C).

Но я ничего не вижу, например. Язык программирования C, второй выпуск (который, как я полагаю, был тщательно обновлен для учета всех деталей ANSI C). Но после проверки индекса ссылок на соответствующие слова я ничего не нашел, что обещает это. Страницы 38 и 209, в частности, близки, потому что говорят, что любое выражение, которое может быть оценено во время компиляции, может использоваться там, где может использоваться константа (возможно, с некоторыми ограничениями, если мы достаточно педантичны), и в ней говорится, что такие выражения «may» будут оцениваться во время компиляции, а не «будет»/(некоторый синоним).

Я искал this C89 final draft. Слово «складывание» и «сложение» не дало никаких результатов, а поиск «постоянное выражение» породил 63 совпадения, из которых я проверил примерно половину. Основная часть интереса, по-видимому, в основном такая же, как и книга (она использует слово «может» вместо «может», но в этом контексте они синонимы).

Оба эти логически сильно указывают на то, что каждый компилятор ANSI C должен иметь базовые возможности с постоянной сгибанием, но в то же время, похоже, нет жесткого запрета на компиляцию постоянных выражений в код который вычисляет выражение во время выполнения (такая реализация по-прежнему пользуется постоянными выражениями, поскольку компилятор может генерировать код, который его вычисляет один раз, а затем предполагает, что значение не изменится, и такая реализация может быть вызвана ограничениями в данной базовой архитектуре - например, несколько архитектур RISC должны либо использовать две инструкции для инициализации определенных возможных значений, либо загрузить их из памяти).

Я также коротко искал this C99 final draft, но «складывание» дало один результат без значения, а «сложенный» и «постоянный» имел более ста совпадений, каждый из которых я не мог выделить время для проскальзывания.

Мотивация

Я написал эти макросы для более семантической/Намерения ясности в некотором битом вертеле коде:

#define UCHAR_LOW_N_BITS_m(n) (unsigned char)(UCHAR_MAX >> (CHAR_BIT - (n))) 
#define UCHAR_NTH_BIT_m(n) (unsigned char)(1 << (n)) 

..where n всегда является целым буквальным. Я хочу успокоиться, чтобы услышать обнадеживающий голос: «Все в порядке, каждый используемый C-компилятор, что отдаленно важно, сбросит эти константы для вас». (P.S. Я задал отдельный вопрос о том, должен ли UCHAR_NTH_BIT_m действовать, как если бы bits start from the 0th or 1st bit, надеюсь, в нужном месте.)

И да, нижний может быть превращен в отдельные макросы, например.#define UCHAR_1ST_BIT_m (unsigned char)1 через #define UCHAR_3RD_BIT_m (unsigned char)4 или сколько бы мне ни понадобилось в коде - и пока я не знаю, какой из них лучше, это, вероятно, спорный вопрос, потому что, если я хочу быть хорошим педантичным языком-адвокатом типа C программист, я не могу точно избегать верхнего (нужно убедиться, что код правильно подходит для этих реализаций DSP/встроенных и старомодных мейнфреймов C).

+1

Это зависит от разработчика компилятора. «Can» является «американским» для «may» и означает, что вам разрешено, но вам не нужно это делать. И да, любой хороший компилятор сделает это. –

+0

Я не думаю, что использование «can» ограничено американским английским языком. – dreamlax

+0

@ KlasLindbäck: Я ценю разъяснение, но я знал: именно поэтому я сказал «похоже, в основном, то же самое» - потому что я понял, что, хотя есть различие в формулировках, это означало, по сути, одно и то же. Я отредактирую его, чтобы уменьшить вероятность дальнейшего недоразумения. – mtraceur

ответ

5

В стандарте C термин для компиляции это время перевод, и события, которые происходят во время компиляции может быть описана как при переводе. Вы можете искать стандарт для этих условий.

Ближайшая вещь в этом стандарте к вашей теме - это определение постоянного выражения в разделе 6.6 (C11). Обзор:

Постоянное выражение может быть оценено во время перевода, а не во время выполнения, и, соответственно, может использоваться в любом месте, где может быть константа.

Обратите внимание, что «может быть» не означает «должно быть». Мы ожидаем, что компилятор хорошего качества будет оценивать постоянные выражения во время компиляции, хотя это не является абсолютным требованием.

Раздел 6.6 является слишком большим, чтобы вставить все это здесь, но, консультируясь с C-стандартом (или черновиком, таким как N1570), вы можете прочитать, какие выражения определены как константные выражения, и было бы разумно предположить что ваш компилятор оценивает их во время компиляции.

Если n >= 0 && n < CHAR_BIT * sizeof(int) - 1 и n является постоянным выражением целого числа, то (unsigned char)(1 << (n)) является постоянным выражением целого числа, потому что: его операнды являются целыми константами, он не использует один из операторов, которые запрещены в постоянных выражениях (например, ++), и бросок разрешен, потому что он отличает от целочисленного типа к другому целочисленному типу.

Если n вне этого диапазона, выражение не является постоянным выражением и вызывает неопределенное поведение.

Ваше другое выражение похоже; это ICE, пока CHAR_BIT - n попадает в тот же допустимый диапазон.

4

В целом, стандарт C не указывает, как что-то скомпилировано. Вы никогда не получите гарантии, что один способ реализовать что-то быстрее, чем другой. Нет никакой гарантии, что постоянная фальцовка должна произойти, но поскольку компилятор должен иметь возможность оценивать постоянные выражения во время компиляции (обрабатывать директивы #if и деклараторы массивов), весьма вероятно, что компилятор делает постоянную фальцовку. В конце концов, нет смысла делать постоянную складку, но затем не делать этого.

+0

Это более или менее то, о чем я думал. Я сделал это, и я приму это через день или два, если не появится лучший ответ. – mtraceur

+0

Содержимое директив '# if' оценивается препроцессором, а не компилятором, но константные выражения допускаются в объявлениях массивов, которые обрабатываются компилятором. – supercat

+0

@supercat В стандарте не сказано, как реализован компилятор, он просто указывает ряд фаз перевода, из которых первые несколько обычно реализуются в препроцессоре. – fuz

 Смежные вопросы

  • Нет связанных вопросов^_^