2009-06-21 6 views
3

Ich brauche systemspezifische Funktionen, z. ftello() (definiert in stdio.h nach POSIX-Standard). Ich brauche auch Standard-C++ - Funktionen, z. std::sprintf() (definiert in cstdio, gemäß ISO C++ Standard).Korrekte Reihenfolge, um sowohl <cstdio> als auch <stdio.h> einzuschließen?

AFAIK, einschließlich nur <cstdio> garantiert nicht die Definition nicht-Standard-C++ Zeug, also denke ich, dass ich beide einschließen muss. Ich habe vor langer Zeit gelesen, dass es (zum Beispiel) bei gcc Probleme mit der Include-Datei gibt.

Also, was ist die richtige Reihenfolge für die Aufnahme von <cstdio> und <stdio.h>? Ich suche nach einer Lösung, die so plattformübergreifend wie möglich ist (zumindest für gcc, suncc, intel C++/linux und mingw).

Antwort

2

OK, nach etwas mehr Forschung kam ich schließlich zu der Schlussfolgerung, dass einschließlich der C++ Header zuerst, C Header später ist die richtige Sache zu tun. Betrachten wir zum Beispiel die folgende C++ 0x-Header (von gcc):

/usr/include/c++/4.3/tr1_impl/cstdint:


// ... 
#define __STDC_LIMIT_MACROS 
#define __STDC_CONSTANT_MACROS 
#include_next <stdint.h> 
// ... 

Was sie tut, ist, dass sie definiert zwei C99 Makros und nur dann enthält die C99 stdint.h-Header. Der Grund dafür ist, dass in C99 einige der Funktionen von stdint.h optional sind und nur verfügbar sind, wenn diese Makros definiert sind. In C++ 0x sind jedoch alle stdint.h-Features obligatorisch. Nun, wenn ich die C99 stdint.h zuerst, Cstdint später, würde ich nicht die obligatorischen C++ 0x Funktionen wegen der Header-Wachen in stdint.h erhalten. Man könnte argumentieren, dass dies der Fehler des Compiler-Anbieters ist, aber das wäre falsch. stdint.h ist ein System-gebündelter Header (in diesem Fall von glibc), der ein C99-Header ist und nichts über C++ 0x (es kann schließlich ein altes System sein) oder gcc weiß. Der Compiler kann nicht wirklich alle Systemheader korrigieren (in diesem Fall, um diese Features immer im C++ - Modus zu aktivieren), muss jedoch C++ 0x-Unterstützung auf diesen Systemen bereitstellen, sodass der Anbieter stattdessen diese Problemumgehung verwendet.

2

Bei Systemheaderdateien sollte die Reihenfolge der Aufnahme im Allgemeinen keine Fehlerquelle sein.

Für andere Header-Dateien werfen Sie einen Blick auf die similar question here at SO.

+0

Danke für die Antwort. Ich glaube, ich hier ein ähnliches Problem gefunden: http://gcc.gnu.org/ml/libstdc++/2003-01/msg00210.html ich über ihn vor einer Weile tatsächlich gestolpert, aber ich kann mich nicht erinnern die Details. Die Header waren definitiv System durch. Während dies ein System/Compiler-Problem ist, was ich gefragt habe ist, dass vielleicht jemand eine erprobte Methode der Umgang mit dieser Art von Sachen kennt. – Alex

0

Von was ich sagen kann, sind ftello() und sprintf() beide in stdio.h enthalten.

Die Reihenfolge, in der die Reihenfolge bei nicht standardmäßigen Headern berücksichtigt werden kann, muss überprüft werden, um festzustellen, welche Abhängigkeiten voneinander abhängig sind, und sie in der richtigen Reihenfolge einbeziehen.

Aus diesem Grund sollten Abhängigkeiten von Include-Dateien in der Include-Datei enthalten sein, und nicht auf den "Benutzer" angewiesen werden, um sicherzustellen, dass sie ordnungsgemäß enthalten sind.

+0

Ja, ftello() und sprintf() sind von stdio.h, aber ich spreche von std :: sprintf(), die möglicherweise identisch sind mit sprintf(). In der Tat ist es wahrscheinlich nicht, weil sprintf() ist in der Regel ein Compiler-Makro definiert, während std :: sprintf() ist garantiert, dass eine Funktion (die Sie Adresse nehmen können). Also muss ich ftello() von stdio.h und std :: sprintf() von cstdio verwenden. Beide sind von Standard-Include-Dateien, aber da diese beiden Dateien eine spezielle Beziehung haben, weiß ich nicht, welche die richtige Reihenfolge ist, die zuverlässig auf verschiedenen Compiler/OS-Kombinationen funktioniert. – Alex

2

Ich kenne keine wahre Regel, aber im Allgemeinen schließe ich die niedrigeren Systembibliotheken vor den höheren Bibliotheken ein.

Also in diesem Fall stdio.h ist ein C-Header und (in meiner Vorstellung) ist näher an der Maschine, und <cstdio> ist höhere Ebene, C++ Standard-Bibliothek, die ich vorstellen, mehr abstrahiert werden.

Ich neige dazu, stdio.h vor cstdio mich selbst, aber ich kenne keine genaue Begründung, um diese Begründung zu unterstützen.

0

Sie sorgen sich aus keinem guten Grund. Die Inhalte von <cstdio> sind "wie durch Einschluss" diejenigen von <stdio.h> (17.4.1.2 Header/4). Die Deklarationen und Definitionen (aber nicht die Makros) befinden sich jedoch im Namespace std.

Sie müssen also möglicherweise std::ftello() schreiben. Um eine bessere Portabilität zu erreichen, werfen Sie eine using std::ftello; ein und Sie müssen sich auch nicht darum kümmern.

+0

Ftello() ist nicht in C++ - Standard, und es gibt keine Ftello() im Namespace std (zumindest in gcc's libstdC++). Danke trotzdem! – Alex

+0

Das ist genau mein Punkt. Der C++ - Standard spezifiziert nicht genau, was in stdio.h ist. Es sagt nur, dass cstdio alles enthält, was in stdio.h ist, aber in Namespace std. Wenn libstdC++ ftello in stdio.h, aber nicht in cstdio einfügt, verstößt es gegen 17.4.1.2. – MSalters

0

Ich lege die spezifischsten Sachen an die Spitze und die am wenigsten spezifischen Sachen an die Unterseite. Für eine Quelldatei zum Beispiel würde es so aussehen:

  1. vorkompilierte Header, falls vorhanden
  2. -Header für diese Quelldatei
  3. Projekt
  4. meist spezifische Bibliotheken, zum Beispiel Bibliotheken in diesen enthalten Projekt oder Firmenbibliotheken
  5. Least spezifische Bibliotheken, wie "System" Bibliotheken wie Boost, oder SDL
  6. Standard C++
  7. Standard C
  8. Betriebssystem Header

Meine Begründung ist, dass die spezifischeren Header oft generische Header enthalten, und wollen, dass sie über Makros ändern. Wenn diese bereits enthalten sind, schließen Wächter ein, oder Standardmakrowerte werden das Verhalten für Systembibliotheken stören. Ein weiterer Grund ist, dass diese Anordnung verhindert, dass Abhängigkeiten von anderen Headern "versteckt" werden, das heißt, dass diese Headern nicht alleine stehen, wenn sie von anderen Quelldateien enthalten sind, da sie immer Systembibliotheken vor sich selbst enthalten haben.

+0

Das ist meine Einschlussreihenfolge auch. :) Außer ich verschiebe 5 aus irgendeinem Grund nach 8. –