Nei vecchi tempi (pre-ANSI), predefinire simboli come unix
ed vax
era un modo per consentire al codice di rilevare in fase di compilazione per quale sistema veniva compilato. All'epoca non esisteva uno standard linguistico ufficiale (oltre al materiale di riferimento sul retro della prima edizione di K&R), e il codice C di qualsiasi complessità era in genere un complesso labirinto di #ifdef
s per consentire differenze tra i sistemi. Queste definizioni macro sono state generalmente impostate dal compilatore stesso, non definito in un file di intestazione della libreria. Poiché non c'erano regole reali su quali identificatori potevano essere utilizzati dall'implementazione e quali fossero riservati ai programmatori, gli autori di compilatori si sentivano liberi di usare nomi semplici come unix
e presumevano che i programmatori avrebbero semplicemente evitato di usare quei nomi per i propri scopi.
Lo standard ANSI C del 1989 ha introdotto regole che limitano quali simboli un'implementazione potrebbe legalmente predefinire. Una macro predefinita dal compilatore potrebbe avere solo un nome che inizia con due caratteri di sottolineatura o con un carattere di sottolineatura seguito da una lettera maiuscola, lasciando i programmatori liberi di usare identificatori che non corrispondono a quel modello e non usati nella libreria standard.
Di conseguenza, qualsiasi compilatore che predefinisce unix
o linux
non è conforme, poiché non riuscirà a compilare un codice perfettamente legale che utilizza qualcosa di simile int linux = 5;
.
Come succede, gcc non è conforme per impostazione predefinita - ma può essere reso conforme (ragionevolmente bene) con le giuste opzioni della riga di comando:
gcc -std=c90 -pedantic ... # or -std=c89 or -ansi
gcc -std=c99 -pedantic
gcc -std=c11 -pedantic
Vedi il manuale di gcc per maggiori dettagli.
gcc eliminerà gradualmente queste definizioni nelle versioni future, quindi non dovresti scrivere codice che dipende da esse. Se il tuo programma deve sapere se è stato compilato per un target Linux o meno, può verificare se __linux__
è definito (supponendo che tu stia usando gcc o un compilatore compatibile con esso). Vedere il manuale del preprocessore GNU C per ulteriori informazioni.
A parte in gran parte irrilevante: il vincitore del "Best One Liner" dell'International Obfuscated C Code Contest del 1987 , di David Korn (sì, l'autore del Korn Shell) ha approfittato della unix
macro predefinita :
main() { printf(&unix["\021%six\012\0"],(unix)["have"]+"fun"-0x60);}
Stampa "unix"
, ma per motivi che non hanno assolutamente nulla a che fare con l'ortografia del nome della macro.