Что означает ошибка компилятора "отсутствующий двоичный оператор перед маркером"?

Недавно я попытался скомпилировать gcc:

ошибка: отсутствующий двоичный оператор перед токеном "("

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

Когда и почему gcc испускает эту ошибку?

Ответ 1

Это не ошибка компилятора, это ошибка препроцессора. Это происходит, когда препроцессор сталкивается с недопустимым синтаксисом при попытке оценить выражение в директиве #if или #elif.

Одной из общих причин является оператор sizeof в директиве #if:

Например:

  #define NBITS (sizeof(TYPE)*8)
  //later
  #if (NBITS>16)    //ERROR

Это ошибка, потому что sizeof оценивается компилятором, а не препроцессором.

Тип приведения также недействителен синтаксисом препроцессора:

  #define ALLBITS ((unsigned int) -1)
  //later
  #if (ALLBITS>0xFFFF)    //ERROR

Здесь правила для допустимого выражения.

Обратите внимание, что #if будет оценивать макрос undefined как 0, если только он не выглядит так, как будто он принимает аргументы, и в этом случае вы также получите эту ошибку:

Итак, если THIS - undefined:

#if THIS == 0  //valid, true

#if THIS > 0 //valid, false

#if THIS() == 0  //invalid. ERROR

Опечатки в инструкции #if также могут вызывать это сообщение.

Ответ 2

Если вы работаете в Linux, убедитесь, что в файлах вашего проекта нет заголовка с именем features.h. У меня был один с этим именем, что привело к:

/usr/include/x86_64-linux-gnu/bits/huge_val.h:25: ошибка: ожидается указатель на функцию

или же

/usr/include/bits/huge_val.h:26:18: ошибка: отсутствует двоичный оператор перед токеном "("

Это связано с тем, что некоторые системные заголовки, такие как huge_val.h используют макросы, такие как __GNUC_PREREQ, которые определены в /usr/include/features.h (подробнее об этом заголовке __GNUC_PREREQ в этом вопросе SO).

В моем случае я впервые увидел эту ошибку, когда начал использовать опцию gcc -I, которая неожиданно заставила gcc выбрать каталог для включения моего проекта до того, как стандартные каталоги включения системы.

Ответ 3

Иногда вы получаете эту ошибку, если у вас есть -fno-operator-names в флагах вашего компилятора. Я пострадала от точной ошибки при сборке json, и это решило ее.