In den alten Tagen (vor ANSI) war das Vordefinieren von Symbolen wie unix
und vax
eine Möglichkeit, mit der Code zur Kompilierungszeit erkennen konnte, für welches System er kompiliert wurde. Damals gab es keinen offiziellen Sprachstandard (über das Referenzmaterial auf der Rückseite der ersten Ausgabe von K & R hinaus), und C-Code jeglicher Komplexität war normalerweise ein komplexes Labyrinth von #ifdef
s, um Unterschiede zwischen Systemen zu berücksichtigen. Diese Makrodefinitionen wurden im Allgemeinen vom Compiler selbst festgelegt und nicht in einer Bibliotheksheaderdatei definiert. Da es keine wirklichen Regeln gab, welche Bezeichner von der Implementierung verwendet werden könnten und welche für Programmierer reserviert waren, konnten Compiler-Autoren einfache Namen wie verwenden unix
und gingen davon aus, dass Programmierer diese Namen einfach nicht für ihre eigenen Zwecke verwenden würden.
Mit dem ANSI C-Standard von 1989 wurden Regeln eingeführt, die einschränken, welche Symbole eine Implementierung rechtlich vordefinieren kann. Ein vom Compiler vordefiniertes Makro kann nur einen Namen haben, der mit zwei Unterstrichen beginnt, oder mit einem Unterstrich, gefolgt von einem Großbuchstaben. So können Programmierer Bezeichner verwenden, die nicht mit diesem Muster übereinstimmen und nicht in der Standardbibliothek verwendet werden.
Infolgedessen jeder Compiler, der vordefiniert unix
oder linux
nicht konform ist, da er keinen perfekt legalen Code kompilieren kann, der so etwas verwendet int linux = 5;
.
Zufällig ist gcc standardmäßig nicht konform - es kann jedoch so eingestellt werden, dass es (ziemlich gut) mit den richtigen Befehlszeilenoptionen übereinstimmt:
gcc -std=c90 -pedantic ... # or -std=c89 or -ansi
gcc -std=c99 -pedantic
gcc -std=c11 -pedantic
Weitere Informationen finden Sie im gcc-Handbuch .
gcc wird diese Definitionen in zukünftigen Versionen auslaufen lassen, daher sollten Sie keinen Code schreiben, der von ihnen abhängt. Wenn Ihr Programm wissen muss, ob es für ein Linux-Ziel kompiliert wird oder nicht, kann es prüfen, ob __linux__
es definiert ist (vorausgesetzt, Sie verwenden gcc oder einen damit kompatiblen Compiler). Weitere Informationen finden Sie im GNU C-Präprozessorhandbuch .
Abgesehen davon weitgehend irrelevant: Der "Best One Liner" -Sieger des Internationalen Obfuscated C Code Contest von 1987 von David Korn (ja, der Autor der Korn Shell) nutzte das vordefinierte unix
Makro:
main() { printf(&unix["\021%six\012\0"],(unix)["have"]+"fun"-0x60);}
Es wird gedruckt "unix"
, aber aus Gründen, die absolut nichts mit der Schreibweise des Makronamens zu tun haben.