Сомнение в условном включении - PullRequest
3 голосов
/ 29 декабря 2010

Это фактически извлечено из моего модуля (препроцессор в C)

Условное выражение может содержать любой оператор C, кроме операторов присваивания, приращения и декремента.

Я не уверен, получаю ли я это утверждение или нет, поскольку я пытался использовать this , и это сработало. Также для других манипуляций вероятным обходным решением было бы простообъявите макрос или функцию внутри условного выражения, что-то вроде этого, чтобы быть точным .

Также я не понимаю, каково обоснование этого правила.Может кто-нибудь объяснить?

Спасибо

Ответы [ 3 ]

5 голосов
/ 29 декабря 2010

Вы, похоже, неправильно поняли, к чему относится выражение условное выражение .
В этом фрагменте

#if defined TEST
  int a = 0;
#endif

Условное выражение - это часть, проверяемая #if, то есть это часть defined TEST.

Причина, по которой присваивание, увеличение и уменьшение не допускаются, заключается в том, что эти операторы хотят изменить переменную, что бессмысленно в контексте препроцессора.
Препроцессор работает полностью на основе текстовой подстановки и оценки результирующих константных выражений.

Если у вас есть этот код

#define X a++
#define Y 42

#if X == Y
#endif

Затем в тесте #if X == Y сначала X и Y заменяются их макроразложением (соответственно a++ и 42), в результате чего

#if a++ == 42

Далее a заменяется расширением макроса. Поскольку макроса a нет, замена определяется как результат 0:

#if 0++ == 42

Теперь нет возможных имен макросов для расширения, поэтому препроцессор пытается оценить условие. Поскольку есть попытка увеличить постоянную 0, эта оценка завершается с ошибкой.

4 голосов
/ 29 декабря 2010

Условное выражение может содержать любой оператор C за исключением операторы присваивания, приращения и операторы декремента.

Это говорит, что вы не можете написать это,

#if X = 4 //wrong

#if X++  //this too wrong

#if X-- //this too

EDIT:

Я только что прочитал ваш комментарий к сообщению Диего Севильи ,

Согласен, но почему-то так (ideone.com/ahXDA) не разрешено? - Philando Gullible

Этот код фактически эквивалентен тому, который вы пишете в глобальной области видимости,

//global code
int b=7; 
b++;  //ill-formed!

Что не разрешено в C (и C ++). Это, однако, разрешено только в C,

//legal in C Only
int b = 7;
int b; //well-formed!

Здесь второе определение называется предварительное определение . Стандарт C говорит в $ 6,9,2 / 2,

Объявление идентификатора для объект, который имеет область видимости без инициализатор и без спецификатор класса хранения или с статический спецификатор класса хранения, составляет предварительное определение . Если единица перевода содержит одно или несколько предварительных определений для идентификатора, а единица перевода не содержит внешнего определения для этого идентификатора, то поведение точно такое, как если бы единица перевода содержит файл объявление области этого идентификатора с составным типом на конец единицы перевода, с инициализатором, равным 0.

Что опять же означает, что следующее не разрешено,

//illegal in both C and C++
int b=7;
int b=8; //error 

Это уже не предварительное определение. Это переопределение, которое не допускается!

1 голос
/ 29 декабря 2010

Абзац, выделенный жирным шрифтом, относится к #if выражениям, поэтому вы можете использовать операторы:

#if VARIABLE > 3

и т. Д., А не код, который находится внутри макросов, которые вы определяете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...