Макросы являются просто текстовой заменой, таким образом, в Вашем примере, пишущий TIMER_100_MS
в программе необычный способ записать 32768 / 10
.
Поэтому вопрос состоит в том, когда компилятор оценил бы 32768 / 10
, который является постоянным интегральным выражением. Я не думаю, что стандарт требует какого-то конкретного поведения здесь (так как оценка и времени компиляции во время выполнения неразличима в действительности), но любой промежуточный достойный компилятор оценит его во время компиляции.
Я не знаю ни о каком стандарте, который гарантирует, что будет оптимизирован. Препроцессор заменит 32768/10 TIMER_100_MS, который Вы видите путем выполнения gcc-c. Чтобы видеть, оптимизирует ли компилятор далее, выполняет gcc-S и проверяют ассемблер. С gcc 4.1, даже без любых флагов оптимизации, это уменьшается до константы во время компиляции:
#include <stdlib.h>
#include <stdio.h>
#define EXTERNAL_CLOCK_FREQUENCY 32768
#define TIMER_1_S EXTERNAL_CLOCK_FREQUENCY
#define TIMER_100_MS TIMER_1_S / 10
int main(int argc, char **argv)
{
printf("%d\n", TIMER_100_MS);
return(0);
}
gcc -S test.c
cat test.s
...
popl %ebx
movl $3276, 4(%esp)
leal LC0-"L00000000001$pb"(%ebx), %eax
movl %eax, (%esp)
call L_printf$stub
...
Большинство ответов в здесь сфокусированном на эффекте макроподстановки. Но я думаю, что он хотел знать, оценен ли
32768 / 10
во время компиляции. В первую очередь, это - арифметическое константное выражение и кроме того интегральное константное выражение (потому что это только получило литералы целого типа). Реализация является бесплатной вычислить его во времени выполнения, но это должно также смочь вычислить его во время компиляции, потому что
, Если компилятор может преимущественно вычислить результат уже во время компиляции, он должен использовать то значение и не повторно вычислить его во времени выполнения, я думаю. Но возможно существует некоторая причина все еще, чтобы сделать это. Я не знал бы.
Редактирование : я сожалею, что ответил на вопрос, как будто это было о C++. Замеченный сегодня Вы спросили о C. Переполнение в выражении считают как неопределенное поведение в C, независимо от того, происходит ли это в константном выражении или нет. Вторая точка также верна в C, конечно.
Редактирование : Как комментарий отмечает, если бы макросом заменяют в выражение как 3 * TIMER_100_MS
, то это оценило бы (3 * 32768) / 10
. Поэтому простой и прямой ответ "нет, Он не произошел бы во времени выполнения каждый раз, потому что подразделение не может произойти вообще из-за приоритета и правил ассоциативности" . Мой ответ выше предполагает, что макросом всегда заменяют таким образом, что подразделение на самом деле происходит.
Компилятор должен оптимизировать то выражение. Я не думаю, что это вознаграждено стандартом, но я никогда не видел компилятор, который НЕ выполнил бы ту задачу.
Однако Вы не должны писать:
#define TIMER_100_MS TIMERB_1_S / 10
..., потому что это - неизбежная ошибка. Необходимо всегда заключать в скобки #defines, включающий выражения.
#define TIMER_100_MS (TIMERB_1_S / 10)
Рассмотрите:
i = 10 * TIMER_100_MS;
первый случай дал бы 32768 ((10 * TIMERB_1_S) / 10), вторые 32760 (10 * (TIMERB_1_S / 10)). Не критическое различие здесь, но НЕОБХОДИМО знать о нем!
Будет, операция 32768 / 10 происходит во времени выполнения каждый раз, когда я использую макрос TIMERB_100_MS?
Каждое место в Вашем коде, где Вы используете TIMERB_100_MS
, это будет заменено 32768 / 10
препроцессором.
, Становится ли то выражение далее оптимизированным (оно оценивает к константе) до Вашего компилятора.
Люди, это преобразование называют "сворачиванием констант", и даже большинство студенческих компиляторов делает это. Пока Вам создал компилятор кто-то не Вы или Ваш сосед по комнате колледжа, и Вы компилируете статически типизированный язык, можно рассчитывать на него даже без включенной оптимизации. Это - другой разговор, если Вы имеете дело с некоторым дурацким динамическим языком, которому позволяют изменить значение /
.
Во время компиляции. Это - стандарт языка (и всегда были), и независимый на компиляторе.
Редактирование
комментатор А попросил ссылку - заключающий в кавычки из "Языка программирования C" 2-й выпуск Приложение A12.3 (p. 229):
А управляют строкой формы
#define identifier token-sequence
причины препроцессор для замены последующих экземпляров идентификатора с данной последовательностью маркеров; при продвижении и запаздывании пробелом вокруг последовательности roken является Конец discaded
редактирования
От Проект Комитета WG14/N1124 — 6 мая 2005 ISO/IEC 9899:TC2:
6.6 Константных выражений
Синтаксис
константное выражение:
условное выражениеОписание
, константное выражение может быть оценено во время перевода, а не времени выполнения, и соответственно может использоваться в любом месте, что константа может быть.
Ограничения
Константные выражения не должны содержать присвоение, инкремент, декремент, вызов функции или операторы запятой, кроме тех случаев, когда они содержатся в подвыражении, которое не оценено 96)
Каждое константное выражение должно оценить к константе, которая находится в диапазоне epresentable значений для его типа.