2012-04-24 8 views
9

Angenommen, die folgende Header-Datei entspricht z. B. einer gemeinsam genutzten Bibliothek. Die exportierte Funktion nimmt einen Zeiger auf eine benutzerdefinierte Struktur in diesem Header definiert:C struct Alignment und Portabilität über Compiler hinweg

// lib.h 

typedef struct { 
    char c; 
    double d; 
    int i; 
} A; 

DLL_EXPORT void f(A* p); 

Wenn die gemeinsam genutzte Bibliothek gebaut wird einen Compiler und dann von C-Code mit einem anderen Compiler gebaut verwendet wird, ist es vielleicht nicht wegen eines anderen Arbeit Speicherausrichtung, wie Memory alignment in C-structs vorschlägt. Gibt es eine Möglichkeit, meine Strukturdefinition über verschiedene Compiler auf derselben Plattform portierbar zu machen?

Ich interessiere mich speziell für Windows-Plattform (anscheinend hat es keine gut definierten ABI), obwohl neugierig wäre, auch über andere Plattformen zu lernen.

+3

Nein, es sei denn jemand hat Ihnen das garantiert. –

+3

Kein Duplikat. Zumindest nicht von der Frage ausgewählt. Dieser kann alleine stehen. –

+1

Ist eine Frage, die Wörter "struct alignment" enthält, automatisch ein Duplikat dieser anderen Frage, selbst wenn es nichts damit zu tun hat? .. –

Antwort

11

TL; DR in der Praxis sollte es dir gut gehen.

Der C-Standard definiert dies nicht, aber eine Plattform ABI tut dies im Allgemeinen. Das heißt, für eine gegebene CPU-Architektur und ein bestimmtes Betriebssystem kann eine Definition für die Zuordnung von C zu Assembly vorhanden sein, die die Zusammenarbeit verschiedener Compiler ermöglicht.

Struct Alignment ist nicht die einzige Sache, die eine Plattform ABI definieren muss, Sie haben auch Funktionen, die Konventionen und solche Sachen aufrufen.

C++ macht es noch komplexer und das ABI hat vtables, Ausnahmen, Namen Mangeln usw.

Unter Windows Ich denke, es gibt mehr C++ ABIs je nach Compiler aber C ist weitgehend kompatibel über Compiler angeben. Ich könnte mich irren, kein Windows-Experte.

Einige Links:

Wie auch immer das Endergebnis ist, dass Sie suchen Ihre Garantie in der Plattform/Compiler ABI-Spezifikation, nicht der C-Standard.

+0

Danke für Ihre Bemühungen, obwohl meine Frage C++ überhaupt nicht betrifft. Ich kenne ABI, deshalb habe ich die Frage Windows-spezifisch markiert, da ich noch nie von ABI-Spezifikationen unter Windows gehört habe. –

+0

@ 7vies: C hat auch einen ABI (denke an die verschiedenen Aufrufkonventionen, cdecl, stdcall, fastcall). Es ist nur so, dass die verschiedenen Compiler für C die gleichen sind (zumindest für die "normalen" Aufrufkonventionen), und zwar aus keinem anderen Grund als dem, was das Betriebssystem für Systemaufrufe erwartet. Mit C++ stimmen die verschiedenen Compiler * oft * nicht mit der gleichen API überein, insbesondere für externe Namen. –

+0

@MichaelBurr, als eine Randnotiz, sagt Wikipedia, dass dies _x86_ Konventionen sind, werden sie auch auf anderen Architekturen verwendet? Ich bin mir der C++ - Probleme bewusst, deshalb frage ich, wie man es in reinem C macht. Aufrufkonventionen helfen beim Definieren einer portablen Schnittstelle, lösen aber nicht mein Problem mit der Strukturausrichtung. –

1

Nicht nur, dass es nicht garantiert ist, aber selbst wenn Sie den gleichen Compiler verwenden, kann es Unterschiede aufgrund unterschiedlicher Compilerschalter im Build geben, oder wenn Sie verschiedene Versionen desselben Compilers und derselben Switches verwenden ein eingebetteter Compiler, an dem ich gearbeitet habe).

Sie müssen stellen Sie sicher, dass die Strukturen genau das gleiche sind, verwenden Sie Schalter, #pragmas, was auch immer die Compiler Ihnen gibt.

Mein Rat - weit weg davon zu bleiben. Übergeben Sie Ihre Argumente in der Funktion, nicht in einer Struktur eingeschlossen.

Und selbst in dieser einfachen Form, wenn Sie mit zwei Compilern umgehen, ist es nicht trivial. Sie müssen sicherstellen, dass ein int beispielsweise die gleiche Anzahl an Bytes annimmt. Auch der Aufruf von conevntion - Argumente Reihenfolge - von links nach rechts oder von rechts nach links - kann zwischen Compiler unterscheiden.

3

Die einzige Möglichkeit, um sicher zu wissen, ist die Dokumentation der betreffenden Compiler zu konsultieren.Es ist jedoch in der Regel der Fall, dass das C-Struct-Layout (außer für Bitfelder) durch eine ABI-Beschreibung für die von Ihnen verwendete Umgebung definiert wird und C-Compiler dem nativen ABI folgen.