В старые времена (до ANSI) предопределенные символы, такие как unix
и, vax
позволяли коду определять во время компиляции, для какой системы он компилируется. В то время не было никакого официального языкового стандарта (кроме справочного материала в конце первого издания K & R), и C-код любой сложности, как правило, представлял собой сложный лабиринт #ifdef
s для учета различий между системами. Эти определения макросов обычно устанавливались самим компилятором, а не определялись в заголовочном файле библиотеки. Поскольку не было настоящих правил о том, какие идентификаторы могут использоваться реализацией, а какие зарезервированы для программистов, разработчики компиляторов могут свободно использовать простые имена, такие как, unix
и предполагают, что программисты просто избегают использовать эти имена в своих целях.
Стандарт ANSI C 1989 года ввел правила, ограничивающие символы, которые могут быть юридически определены реализацией. Макрос, предопределенный компилятором, может иметь только имя, начинающееся с двух подчеркиваний или со знака подчеркивания, за которым следует заглавная буква, что позволяет программистам использовать идентификаторы, не соответствующие этому шаблону и не используемые в стандартной библиотеке.
В результате любой компилятор, который предопределяет unix
или linux
не соответствует, так как он не сможет скомпилировать совершенно легальный код, который использует что-то вроде int linux = 5;
.
Так получилось, что gcc по умолчанию не соответствует стандарту, но его можно сделать так, чтобы он соответствовал (достаточно хорошо) нужным параметрам командной строки:
gcc -std=c90 -pedantic ... # or -std=c89 or -ansi
gcc -std=c99 -pedantic
gcc -std=c11 -pedantic
Смотрите руководство gcc для более подробной информации.
gcc будет постепенно отменять эти определения в будущих выпусках, поэтому вы не должны писать код, который зависит от них. Если ваша программа должна знать, компилируется ли она для цели Linux или нет, она может проверить, __linux__
определена ли она (при условии, что вы используете gcc или совместимый с ним компилятор). См. Руководство препроцессора GNU C для получения дополнительной информации.
В значительной степени это не имеет значения: победитель «Best One Liner» Международного конкурса по кодированию кода C в 1987 году Дэвид Корн (да, автор Korn Shell) воспользовался предопределенным unix
макросом:
main() { printf(&unix["\021%six\012\0"],(unix)["have"]+"fun"-0x60);}
Он печатает "unix"
, но по причинам, которые не имеют абсолютно никакого отношения к написанию имени макроса.