Hast du es versucht #undef linux, oder vielleicht eine andere Variable verwenden? Ich denke, die Konstante linux wird zum Testen von Betriebssystemen verwendet, z. B. wenn Sie eine plattformübergreifende Anwendung entwerfen und genau wissen müssen, welche API verwendet werden soll (Windows, Mac, Linux, BSD usw.). Es ist nicht in stdio.h, aber es ist immer noch definiert, wenn der Kernel Linux ist. Derselbe Code sollte in Windows keinen Fehler erzeugen, aber die Verwendung von etwas wie Windows oder WINDOWS als Variable wird es wahrscheinlich tun und umgekehrt
– Braden Best
13. Januar 2014 um 6:58 Uhr
Diese Frage wurde auf Quora plagiiert: quora.com/…
– Keith Thompson
1. Mai 2019 um 0:00 Uhr
@BradenBest _WIN32 und ähnliche Matrizen.
– Paul Stelian
1. Mai 2019 um 16:59 Uhr
@KeithThompson Ja, Quora hat dieses neue Partnerprogramm, bei dem Leute dafür bezahlt werden, Fragen zu stellen. Anstatt also eine Q/A-Site zu sein, ist es jetzt ein Wettbewerb um Geld. Die Leute stellen also Fragen vom Typ „kleinster Nenner“, damit sie ihre Auszahlung erhalten. Anscheinend gehört dazu jetzt auch das Plagiieren von anderen Websites wie dem guten alten StackOverflow. Ich habe dort ein Konto, also habe ich es abgelehnt, es gemeldet und eine Antwort geschrieben Bestrafung sowohl des Autors für das Plagiieren als auch der Website dafür, dass dies zugelassen wurde.
– Braden Best
1. Mai 2019 um 17:16 Uhr
Keith Thompson
In den alten Tagen (vor ANSI) wurden vordefinierte Symbole wie z unix und vax war eine Möglichkeit, Code zur Kompilierzeit zu erkennen, für welches System er kompiliert wurde. Damals gab es keinen offiziellen Sprachstandard (außer dem Referenzmaterial am Ende der ersten Ausgabe von K&R), und C-Code jeglicher Komplexität war normalerweise ein komplexes Labyrinth #ifdefs 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 darüber gab, welche Bezeichner von der Implementierung verwendet werden konnten und welche Programmierern vorbehalten waren, fühlten sich Compiler-Autoren frei, einfache Namen wie zu verwenden unix und gingen davon aus, dass Programmierer es einfach vermeiden würden, diese Namen für ihre eigenen Zwecke zu verwenden.
Der ANSI C-Standard von 1989 führte Regeln ein, die einschränken, welche Symbole eine Implementierung legal vordefinieren kann. Ein vom Compiler vordefiniertes Makro konnte nur einen Namen haben, der mit zwei Unterstrichen oder einem Unterstrich gefolgt von einem Großbuchstaben beginnt, sodass Programmierer Bezeichner verwenden können, die nicht mit diesem Muster übereinstimmen und nicht in der Standardbibliothek verwendet werden.
Als Ergebnis kann jeder Compiler, der vordefiniert unix oder linux ist nicht konform, da es keinen vollkommen legalen Code kompilieren wird, der so etwas wie verwendet int linux = 5;.
Zufälligerweise ist gcc standardmäßig nicht konform – aber es kann (ziemlich gut) mit den richtigen Befehlszeilenoptionen konform gemacht werden:
gcc -std=c90 -pedantic ... # or -std=c89 or -ansi
gcc -std=c99 -pedantic
gcc -std=c11 -pedantic
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 dies prüfen __linux__ definiert ist (vorausgesetzt, Sie verwenden gcc oder einen damit kompatiblen Compiler). Sehen das GNU C-Präprozessor-Handbuch für mehr Informationen.
Eine weitgehend nebensächliche Nebensache: der „Best One Liner“-Gewinner des Jahres 1987 Internationaler Wettbewerb für verschleierten C-Codevon David Korn (ja, der Autor der Korn-Shell) nutzte das Vordefinierte unix Makro:
Es druckt "unix"aber aus Gründen, die absolut nichts mit der Schreibweise des Makronamens zu tun haben.
@Sebastian: Ich möchte hier keine Spoiler posten, und ich ermutige jeden, der dies liest, zuerst zu versuchen, den Code selbst zu verstehen. Aber wenn du Ja wirklich aufgeben möchte, habe ich eine Erklärung gepostet: gist.github.com/Keith-S-Thompson/6920347
“In den alten Tagen (vor ANSI) wurden vordefinierte Symbole wie z unix und vax„– Huh? Nach meinem Verständnis war in den alten Tagen die ganze Welt ein vax!
– sqweek
20. September 2016 um 11:24 Uhr
@KeithThompson Es stellt sich heraus, dass in diesem Ausschnitt tatsächlich undefiniertes Verhalten enthalten ist (obwohl es nichts mit dem zu tun hat unix definieren). Ich habe in einem Kommentar zu diesem Kern erklärt, warum, falls Sie oder jemand anderes neugierig ist.
– Joseph Sible – Wiedereinsetzung von Monica
13. Oktober 2018 um 18:24 Uhr
@MatthewBarclay Das -x c ist unnötig; gcc weiß, dass es sich um eine C-Quelldatei handelt .c Suffix. Vielleicht ist diese Version von gcc nicht vor-#define das Makro unix.
– Keith Thompson
26. April 2020 um 20:06 Uhr
rici
Dies scheint eine (undokumentierte) “GNU-Erweiterung” zu sein: [correction: I finally found a mention in the docs. See below.]
Der folgende Befehl verwendet die -dM Option zum Drucken aller Präprozessordefinitionen; Da die Eingabe “Datei” leer ist, zeigt sie genau die vordefinierten Makros. Es wurde mit gcc-4.7.3 auf einer Standard-Ubuntu-Installation ausgeführt. Sie können sehen, dass der Präprozessor standardbewusst ist. Insgesamt gibt es 243 Makros mit -std=gnu99 und 240 mit -std=c99; Ich habe die Ausgabe nach Relevanz gefiltert.
Die “GNU-Standard”-Versionen ebenfalls #define unix. (Verwenden c11 und gnu11 liefert die gleichen Ergebnisse.)
Ich nehme an, sie hatten ihre Gründe, aber es scheint mir, dass die Standardinstallation von gcc (das C-Code mit -std=gnu89 sofern nicht anders angegeben) nicht konform und – wie in dieser Frage – überraschend. Das Verschmutzen des globalen Namensraums mit Makros, deren Namen nicht mit einem Unterstrich beginnen, ist in einer konformen Implementierung nicht erlaubt. (6.8.10p2: „Alle anderen vordefinierten Makronamen müssen mit einem führenden Unterstrich beginnen, gefolgt von einem Großbuchstaben oder einem zweiten Unterstrich“, aber wie in Anhang J.5 (Portabilitätsprobleme) erwähnt, sind solche Namen oft vordefiniert.)
Als ich diese Antwort ursprünglich schrieb, konnte ich in gcc keine Dokumentation zu diesem Problem finden, aber ich habe sie schließlich entdeckt, nicht in C-implementierungsdefiniertes Verhalten noch drin C-Erweiterungen aber in der cpp manueller Abschnitt 3.7.3wo Folgendes vermerkt ist:
Wir stellen alle vordefinierten Makros, die außerhalb des reservierten Namensraums liegen, langsam aus. Sie sollten sie niemals in neuen Programmen verwenden…
Es ist keine Verletzung des C-Standards, da das GCC-Kompilieren für gnu89 oder gnu99 keine Implementierung des C-Standards ist und der C-Standard keine Anforderungen an Dinge stellt, die keine Implementierungen davon sind.
– Eric Postpischil
6. Oktober 2013 um 17:18 Uhr
@EricPostpischil: Das ist sicherlich wahr; es ist einfach eine nicht konforme Implementierung. Allerdings ist -std=c89 die Ursprünglich Einstellung für gcc, daher ist gcc standardmäßig nicht konform. Das ist natürlich nicht illegal, aber man könnte erwarten, dass gcc irgendwann im Verlauf der Erweiterungen gnu89, gnu99, gnu11 entweder die Namespace-Verschmutzung fallen lässt oder sie irgendwo dokumentiert.
– Rici
6. Oktober 2013 um 17:28 Uhr
Ich weiß nicht inwiefern das “-std=c89” ist Ursprünglich Einstellung für gcc“. Die GCC-Software und der gcc-Befehl existieren in vielen verschiedenen Versionen. Die von Apple vertriebene Version hat standardmäßig nicht „-std=c89“.
– Eric Postpischil
6. Oktober 2013 um 17:55 Uhr
@EricPostpischil: Du hast recht. Ich habe mich vertippt. Ich meinte, dass -std=gnu89 ist die Standardeinstellung, und soweit ich weiß, ist sie die Standardeinstellung unter Solaris, Linux und Mac OS X (developer.apple.com/library/mac/documentation/Darwin/Reference/… für letzteres), und es ist derjenige, der den Namensraum verschmutzt. c89 versucht, dem Standard zu entsprechen, also hätte ich keine Beschwerde, wenn es der Standard wäre.
– Rici
6. Oktober 2013 um 19:26 Uhr
@ChrisDodd: Ich habe keine Meinung dazu, ob es eine gute Idee ist oder nicht. Ich bin der festen Überzeugung, dass solche Abweichungen vom Standard in der Dokumentation leicht zu finden sein sollten.
– Rici
6. Oktober 2013 um 19:43 Uhr
Jonathan Leffler
Da linux ist ein eingebautes Makro, das definiert wird, wenn der Compiler unter Linux läuft oder für Linux kompiliert (wenn es sich um einen Cross-Compiler handelt).
Es gibt viele solcher vordefinierten Makros. Mit GCC können Sie Folgendes verwenden:
cp /dev/null emptyfile.c
gcc -E -dM emptyfile.c
um eine Liste von Makros zu erhalten. (Ich habe es nicht geschafft, GCC zur Annahme zu überreden /dev/null direkt, aber die leere Datei scheint OK zu funktionieren.) Mit GCC 4.8.1 unter Mac OS X 10.8.5 erhielt ich die Ausgabe:
Das sind 236 Makros aus einer leeren Datei. Als ich hinzufügte #include <stdio.h> In der Datei stieg die Anzahl der definierten Makros auf 505. Dazu gehören alle Arten von plattformidentifizierenden Makros.
Es (linux) ist auf meinem Mac OS X-Rechner nicht definiert – es läuft kein Linux (na ja, es gibt eine VM, auf der Linux läuft, aber …). Es kann durch die Header definiert werden, die von enthalten sind <stdio.h>; Das Ausführen einer leeren Datei ist möglicherweise nicht dasselbe.
– Jonathan Leffler
6. Oktober 2013 um 16:22 Uhr
Sie können nicht verwenden /dev/null als Quelldatei ohne -x Da es keine Erweiterung hat, weiß gcc nicht, ob es C oder C++ ist. Sie können verwenden gcc -E -dM -x c /dev/null oder gcc -E -dm -x c++ /dev/null um die Liste zu erhalten, ohne eine leere Datei erstellen zu müssen.
– Chris Dodd
6. Oktober 2013 um 19:39 Uhr
@ChrisDodd – Hier funktioniert es. Beachten Sie, sagte ich cpp (der Präprozessor) nicht gcc. Beachten Sie auch, dass ich es nicht gebe /dev/null als Eingabedatei, sondern ich mache es lieber per Redirection /dev/null hinein stdin. Auch @KerrekSB: auf meinem Debian-Rechner linux steht auf der Liste.
– asveikau
7. Oktober 2013 um 0:17 Uhr
@JonathanLeffler: Der erste Schritt könnte einfach “leere Datei.c berühren” ^^ sein. Interessant (und gefährlich!), dass einige Dinge, “die ich in meinem eigenen Programm verwenden könnte, ohne nachzudenken” vom Präprozessor konvertiert werden können! Ex: touch nothing.c ; gcc -E -dM nothing.c | awk '{print $2}' | grep -v '__' : Es zeigt “unix” und “i386” unter den sehr wahrscheinlichen Dingen, die ich in einem Programm haben könnte, ohne mir bewusst zu sein, dass sie vom Präprozessor geändert werden!
– Olivier Dulac
10. Oktober 2013 um 14:05 Uhr
Ja, es könnte. Willst du einen Wettbewerb dafür, wie viele verschiedene Möglichkeiten es gibt, eine leere Datei zu erstellen? Es könnte auch sein > emptyfile.c oder : > emptyfile.c oder dd if=/etc/passwd of=emptyfile.c count=0 oder …
– Jonathan Leffler
10. Oktober 2013 um 14:07 Uhr
rodrigo
Aus info gcc (Hervorhebung von mir):
-ansi
Im C-Modus ist dies äquivalent zu -std=c90. Im C++-Modus ist es äquivalent zu -std=c++98. Dadurch werden bestimmte Funktionen von GCC deaktiviert, die mit ISO C90 (beim Kompilieren von C-Code) oder mit Standard-C++ (beim Kompilieren von C++-Code) inkompatibel sind, wie z asm und typeof Schlüsselwörter, und vordefinierte Makros wie ‘unix’ und ‘vax’ die den von Ihnen verwendeten Systemtyp identifizieren. Es aktiviert auch die unerwünschte und selten verwendete ISO-Trigraph-Funktion. Für den C-Compiler wird die Erkennung des C++-Stils deaktiviert // Kommentare sowie die inline Stichwort.
(Es verwendet Wachs im Beispiel statt Linux denn als es geschrieben wurde, war es vielleicht populärer ;-).
Die Grundidee ist, dass GCC nur versucht, die ISO-Standards vollständig einzuhalten, wenn es mit aufgerufen wird -ansi Möglichkeit.
Verwandte Frage: stackoverflow.com/questions/3770322/…
– Streichholz
18. Oktober 2013 um 12:25 Uhr
Hast du es versucht
#undef linux
, oder vielleicht eine andere Variable verwenden? Ich denke, die Konstantelinux
wird zum Testen von Betriebssystemen verwendet, z. B. wenn Sie eine plattformübergreifende Anwendung entwerfen und genau wissen müssen, welche API verwendet werden soll (Windows, Mac, Linux, BSD usw.). Es ist nicht in stdio.h, aber es ist immer noch definiert, wenn der Kernel Linux ist. Derselbe Code sollte in Windows keinen Fehler erzeugen, aber die Verwendung von etwas wie Windows oder WINDOWS als Variable wird es wahrscheinlich tun und umgekehrt– Braden Best
13. Januar 2014 um 6:58 Uhr
Diese Frage wurde auf Quora plagiiert: quora.com/…
– Keith Thompson
1. Mai 2019 um 0:00 Uhr
@BradenBest _WIN32 und ähnliche Matrizen.
– Paul Stelian
1. Mai 2019 um 16:59 Uhr
@KeithThompson Ja, Quora hat dieses neue Partnerprogramm, bei dem Leute dafür bezahlt werden, Fragen zu stellen. Anstatt also eine Q/A-Site zu sein, ist es jetzt ein Wettbewerb um Geld. Die Leute stellen also Fragen vom Typ „kleinster Nenner“, damit sie ihre Auszahlung erhalten. Anscheinend gehört dazu jetzt auch das Plagiieren von anderen Websites wie dem guten alten StackOverflow. Ich habe dort ein Konto, also habe ich es abgelehnt, es gemeldet und eine Antwort geschrieben Bestrafung sowohl des Autors für das Plagiieren als auch der Website dafür, dass dies zugelassen wurde.
– Braden Best
1. Mai 2019 um 17:16 Uhr