2016-05-14 5 views
0

Wenn mit Clang/LLVM kompiliert (Apple LLVM Version 6.1.0 (Clang-602.0.49) Ziel: x86_64-Apple-Darwin14.3.0) druckt der C-Code unten 22. Ich bin nicht wirklich besorgt über den C-Standard aber ich möchte wissen, ob es eine Möglichkeit gibt, ein Etikett so zu machen, dass bei einem Offset von -8 Byte ein anderes Vierfachwort meiner Wahl vorliegt. Ich möchte, dass es unter Mac OS X und Linux funktioniert.Gibt es Garantien bezüglich der relativen Adressen von __DATA-Etiketten?

#include<stdio.h> 

long long x = 22; 
long long y = 33; 

int main(void) { 
    long long diff = *(&y - 1); 
    printf("%lld\n",diff); 
} 

mit dem entsprechenden Teil des DATA-Bereichs.

.section __DATA,__data 
    .globl _x      ## @x 
    .align 3 
_x: 
    .quad 22      ## 0x16 

    .globl _y      ## @y 
    .align 3 
_y: 
    .quad 33      ## 0x21 

Antwort

2

Der Compiler kann statische/globale Objekte in beliebiger Reihenfolge platzieren. Gleich für Funktionen. Ein Compiler könnte versuchen, "heiße" oder "kalte" Daten oder Funktionen zu gruppieren, um den Cache-Footprint zu reduzieren.

Wenn Sie mehrere Dinge aus einem Basiszeiger referenzieren möchten, fügen Sie sie in eine Struktur oder ein Array ein. Wie @kcraigie in einem Kommentar vorschlägt, ist ein union zwischen einem Array und einer Struktur möglich. (Aber ist wahrscheinlich nicht nützlich).

Array-Layout im Speicher ist garantiert. struct Layout hat auch einige Garantien, aber kann Compiler nicht verbieten, Padding dort zu platzieren, wo Sie es nicht erwarten. Das Layout struct ist jedoch für eine gegebene ABI festgelegt, so dass Sie sich bei allen Compilern, die dieselbe ABI auf derselben Plattform als Ziel haben, auf das gleiche Strukturlayout verlassen können.

Wenn Sie wirklich über das Layout im Speicher kümmern, könnten Sie einen symbolischen Namen zu verschiedenen Array-Elemente geben mit einem enum oder mit Makros GLOBAL_X-global_array[0] oder etwas zu definieren. Ansonsten verwende einfach eine struct, die gut funktioniert, wenn du die Dinge zusammen gruppieren willst, um sie als Block kopieren zu können.


Im Gegensatz zu @ kcraigies Antwort muss der Speicherblock nicht dynamisch zugewiesen werden. Ein statisches Array oder eine statische Struktur wird den Job gut machen. Offensichtlich ist statischer Speicher eine Verschwendung, wenn Sie ihn nicht benötigen: Verwenden Sie nach Möglichkeit einen automatischen (Stapel-) Speicher.


re: Frage in den Kommentaren:

Würde ein Assembler sich direkt neben jedem halten, wenn im Datenteil so platziert?

Ja. Assembler assemblieren nur Bytes in eine Objektdatei, ohne dass es möglich ist, Dinge innerhalb eines Abschnitts innerhalb des Abschnitts zu verschieben. .align Direktiven können Lücken erzeugen, aber wir wissen, dass .align zwischen x und y auf 0 Bytes erweitert wird (wegen der .align vor x, setzen Sie es bereits auf eine 8-Byte-Grenze).

Die verschiedenen Abschnitte (.text/.rodata vs. .data vs. alle benutzerdefinierten Abschnitte) sind nur in ihre endgültige Reihenfolge beim Linken allerdings setzen.

0

Jeder vernünftige C-Compiler sollte sie in zusammenhängenden Speicher setzen, aber es ist nicht garantiert. Die einzige Methode, mit der AFAIK einen Speicherblock entweder auf dem Stack oder Heap (oder global) zuweisen kann, ist dann garantiert zusammenhängender Speicher.

+1

nicht globale gehen in den Datenbereich nicht der Stapel oder der Haufen? –

+0

Ah ja, danke. Meine Antwort wurde korrigiert. – kcraigie

+0

Würde ein Assembler sie direkt nebeneinander halten, wenn sie so in den Datenbereich platziert würden? –