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

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

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

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

#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 макросы взялись?

1 Ответ

19 голосов
/ 30 декабря 2011

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 '.

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

...