Ich habe zahllose Fragen der Form "Ich mag keine Auffüllung, wie schalte ich es aus" gesehen, aber habe noch nichts darüber gefunden, den Compiler zu zwingen, zusätzliche Auffüllung zu bieten.
Der spezielle Fall, dass ich wie
aussieht %Vor% Wo vect2
eine einfache struct {double x; double y;} vect2
ist. Um SSE2 zu verwenden, muss ich ein Paar Doubles laden können, die auf 16-Byte-Grenzen ausgerichtet sind. Dies hat so lange funktioniert, bis ich die zusätzliche int
hinzugefügt habe und meine Strukturgröße von 48 auf 56 Byte erhöht habe. Das Ergebnis ist segfaults.
Gibt es irgendeine Art von Compiler-Direktive, die ich verwenden kann, die entweder sagt: "pad diese Struktur, um es zu einem Vielfachen von 16 Bytes zu machen", oder "diese Struktur hat eine Ausrichtung von 16 Bytes"? Ich weiß, dass ich es manuell machen könnte (zum Beispiel mit einem zusätzlichen Zeichen [12]), aber ich würde dem Compiler lieber sagen (GCC, vorzugsweise ICC - kompatibel), und muss es nicht manuell machen, wenn ich das ändere Struktur in Zukunft.
Ich füge meine eigene Antwort hinzu, falls jemand nach einer Lösung sucht. Marks Lösung ist eine saubere und erfüllt die automatische Anforderung, aber es ist nicht, als ich am Ende ging. Ich wollte das vermeiden, weshalb ich die Frage stellte, aber es gibt eine "triviale" Lösung:
%Vor% Wenn Sie die aktuelle Größe von struct
manuell überprüfen, können Sie eine angemessene Anzahl von Zeichen hinzufügen (oder etwas anderes, aber char
's lassen Sie es in Bytes tun), um die richtige Größe zu erhalten. Dies zeigte sowohl die beste Leistung als auch die Einfachheit, obwohl es jedes Mal aktualisiert werden muss, wenn sich die Struktur ändert. In diesem Fall ist das in Ordnung, aber wenn Sie eine Struktur haben, die die Größe je nach Optionen ändern könnte, wäre das problematisch.
Beachten Sie, dass mein struct
56 Bytes und ich 12 hinzugefügt habe, um es zu 64 zu machen. Diese Mathematik funktioniert nicht, weil das nachgestellte int
bereits um 4 Bytes an der 8-Byte-Grenze aufgefüllt wurde; Die struct
war eigentlich nur 52 Bytes vorher. Das Hinzufügen von nur 5 char
s hätte funktioniert, indem struct
57 Bytes lang gemacht worden wären, was auf 64 aufgefüllt worden wäre, aber das ist keine so schöne Lösung, weshalb ich 12 benutzt habe, um es zum Laufen zu bringen genau.
Sie können zwei Strukturen verschachteln, um sie automatisch aufzufüllen, ohne dass Sie die Größe selbst verfolgen müssen.
%Vor%Diese Version fügt leider 16 Byte hinzu, wenn die Struktur bereits ein Vielfaches von 16 ist. Dies ist unvermeidbar, da der Standard keine Arrays mit der Länge null zulässt.
Einige Compiler erlauben Arrays mit einer Länge von Null als Erweiterung, und in diesem Fall können Sie stattdessen Folgendes tun:
%Vor%Diese Version fügt keine Padding-Bytes hinzu, wenn die Struktur bereits ein Vielfaches von 16 ist.
In gcc
können Sie beliebige Typen und Variablen mit __attribute__((aligned(...)))
abgleichen. Für Ihr Beispiel wäre dies
Dies packt automatisch die Struktur, so dass Arrays davon korrekt ausgerichtet werden.
Die neue C ++ 11-Spezifikation hat dafür auch eine neue Funktion , obwohl ich das nicht tue glaube, dass viele Anbieter sie bereits implementiert haben.
Sie können das Pack-Pragma versuchen, obwohl es nicht von der Spezifikation unterstützt wird. Sowohl GCC als auch MS unterstützen es jedoch.
Dies richtet die Struktur auf 1-Byte-Grenzen aus, obwohl Sie die Zahl beliebig ändern können.
%Vor%Aktualisierung:
Das oben beschriebene funktioniert also anscheinend nicht, da es nur das Auffüllen schrumpft und es niemals erweitert. Bedauerlicherweise habe ich heute Nachmittag keine Testumgebung.
Vielleicht würde die Verwendung einer anonymen Union funktionieren. Ich weiß, dass es auf die größte Größe erweitert wird, obwohl ich nicht weiß, ob Sie sonst irgendwelche Garantien über die Ausrichtung bekommen.
%Vor%Tags und Links c c++ gcc struct memory-alignment