У старі часи (до 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.
В основному неважливо: переможець "Найкращого вкладиша" Міжнародного конкурсу закоханих кодів 1987 р. Девід Корн (так, автор "Корн Шелл") скористався заздалегідь заданим unix
макросом:
main() { printf(&unix["\021%six\012\0"],(unix)["have"]+"fun"-0x60);}
Він друкується "unix"
, але з причин, які не мають абсолютно нічого спільного з написанням імені макросу.