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

В чем причина наличия безоговорочных идентификаторов в качестве встроенных макросов в gcc?

Сегодня я наткнулся на довольно интересную ошибку компилятора:

int main() {
  int const unix = 0; // error-line
  return unix;
}

Дает следующее сообщение с gcc 4.3.2 (да, древний...):

error: expected unqualified-id before numeric constant

что определенно довольно запутанно.

К счастью, clang (3.0) немного полезнее (как обычно):

error: expected unqualified-id
  int const unix = 0
            ^
<built-in>:127:14: note: expanded from:
#define unix 1
             ^

Я, конечно, не ожидал unix, который не написан ни в верхнем регистре, ни начинался с подчеркивания, чтобы быть макросом, особенно встроенным.

Я проверил предопределенные макросы в gcc, и есть 2 (на моей платформе), которые используют "безоговорочные" символы:

$ g++ -E -dM - < /dev/null | grep -v _
#define unix 1
#define linux 1

Все остальные являются "хорошо выполненными" макросами с ведущими символами подчеркивания, используя традиционные зарезервированные идентификаторы, sample:

#define __linux 1
#define __linux__ 1
#define __gnu_linux__ 1

#define __unix__ 1
#define __unix 1

#define __CHAR_BIT__ 8
#define __x86_64 1
#define __amd64 1
#define _LP64 1

(это беспорядок и, похоже, не какой-то конкретный порядок...)

Кроме того, есть много "похожих" символов, поэтому я думаю, что есть проблема обратной совместимости...

Итак, где выходят макросы unix и linux?

4b9b3361

Ответ 1

gcc по умолчанию полностью не соответствует стандарту C.

Вызвать его с помощью -ansi, -std=c99 или -std=c1x и unix не будет предопределено. (-std=c1x , вероятно, станет стал -std=c11 в <предыдущем выпуске gcc-версии будущего.)

Немного запутанно, что это описано в отдельном руководстве для препроцессора GNU, а не в руководстве gcc.

Указание документации по препроцессору GNU (info cpp, версия 4.5):

Стандарт C требует, чтобы все системные макросы были частью "зарезервированное пространство имен". Все имена, начинающиеся с двух символов подчеркивания, или подчеркивание и заглавная буква, зарезервированы для компилятора и библиотеки для использования по своему усмотрению. Однако исторически Макросы, специфичные для системы, имеют имена без специального префикса; для Например, обычно можно найти `unix ', определенный в Unix-системах. Для все такие макросы, GCC предоставляет параллельный макрос с двумя символами подчеркивания добавлен в начале и в конце. Если `unix 'определен, `__unix__ 'также будет определен. Не будет больше двух подчеркивает; Параметр `_mips '-` __mips __'.

Когда опция `-ansi 'или любая опция` -std', которая запрашивает строгую соответствие, предоставляется компилятору, все системные предопределенные макросы вне зарезервированного пространства имен подавляются. параллельные макросы, внутри зарезервированного пространства имен, остаются заданными.

Мы постепенно отказываемся от всех предопределенных макросов, которые находятся за пределами зарезервированное пространство имен. Вы никогда не должны использовать их в новых программах, и мы попробуйте исправить старый код, чтобы использовать параллельные макросы когда вы его найдете. Мы не рекомендуем использовать системные макросы, которые также находятся в зарезервированном пространстве имен. Это лучше в в долгосрочной перспективе, чтобы специально проверить функции, которые вам нужны, используя инструмент таких как `autoconf '.

Текущая версия руководства здесь.