Подтвердить что ты не робот

Существует ли логическое короткое замыкание в препроцессоре C?

gcc docs для cpp объясняют директиву #if:

[...] и логические операции (& & и ||). Последние два подчиняются обычным законам короткого замыкания стандарта C.

Что это значит? Нет оценки выражений во время предварительной обработки, поэтому как это может быть закорочено?

4b9b3361

Ответ 1

Очень просто: макросы undefined имеют числовое значение ноль, а деление на ноль незаконно.

#if FIXEDSIZE && CHUNKSIZE/FIXEDSIZE > 42
#define USE_CELLPOOL
#endif

#if оценивает остальную часть своей строки как целочисленное постоянное выражение. Ваша документация начинается:

Директива '#if позволяет вам проверять значение арифметического выражения, а не просто существование одного макроса.

Это не расширение gcc, синтаксис Standard для #if равен

#if constant-expression new-line group <суб > optсуб > .

Препроцессор C99 обрабатывает все константы как [u]intmax_t.

Ответ 2

К ним относятся && и || операторы для #if

#if defined (AAA) || defined (BBB)

Если defined (AAA) определено, то defined (BBB) никогда не оценивается.


UPDATE

Итак, запуск вычисления будет коротким. Например, если вы создаете с помощью -Wundef, чтобы предупредить об использовании макросов undefined.

#if defined FOO && FOO > 1000
#endif

#if FOO > 1000
#endif

приведет к

thomas:~ jeffery$ gcc foo.c -Wundef
foo.c:4:5: warning: 'FOO' is not defined, evaluates to 0 [-Wundef]
#if FOO > 1000
    ^
1 warning generated.

Таким образом, первая версия не генерирует предупреждение макроса undefined, потому что FOO > 1000 не оценивается.


OLD MUSINGS

Это становится важным, если вторая часть представляет собой макрос, который имеет побочные эффекты. Макрос не будет оцениваться, поэтому побочные эффекты не будут иметь места.


Чтобы избежать злоупотребления макросами, я приведу несколько разумный пример

#define FOO
#define IF_WARN(x) _Pragma (#x) 1
#if defined(FOO) || IF_WARN(GCC warning "FOO not defined")
#endif

Теперь, когда я построил этот пример, я столкнулся с проблемой. IF_WARN всегда оценивается.

Да, больше исследований необходимо.


Ну что ж... теперь, когда я прочитал его снова.

Макросы. Все макросы в выражении расширяются до того, как начнется фактическое вычисление значения выражения.

Ответ 3

Нет оценки выражений во время предварительной обработки, так как это может быть короткозамкнуто?

Да, есть оценка выражения во время предварительной обработки.

C11: 6.10.1 Условное включение (p4):

Перед оценкой макроопределения в списке токенов предварительной обработки, которые станут...

В сноске 166:

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

Эти утверждения ясно свидетельствуют о том, что выполняется оценка выражения при предварительной обработке. Необходимым условием является то, что управляющее выражение должно оцениваться в целочисленное значение.
Теперь оператор && и || будет подчиняться обычным законам короткого замыкания стандарта C, как указано в GNU doc.

Теперь запустите эту программу с помощью и без // и посмотрите результат, чтобы увидеть поведение короткого замыкания:

#include<stdio.h>
#define macro1 1
//#define macro2 1
int main( void )
{
    #if  defined (macro1)  && defined (macro2)
    printf( "Hello!\n" );
    #endif
    printf("World\n"); 
    return 0;
}

Ответ 4

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

A условный - это директива, которая инструктирует препроцессор выбрать включать или не включать фрагмент кода в конечном потоке токенов передается компилятору. Условия препроцессора могут тестировать арифметику выражения или определяется ли имя как макрос, или оба одновременно используя специальный определенный оператор.

Кроме того, он может сократить время компиляции. Изменение следующих оценок может ускорить компиляцию (зависит от реализации компилятора).