Nach dem Kompilieren dieses Codes auf meinem Computer ist mir etwas Merkwürdiges aufgefallen:
#include <stdio.h>
int main()
{
printf("Hello, World!\n");
int a,b,c,d;
int e,f,g;
long int h;
printf("The addresses are:\n %0x \n %0x \n %0x \n %0x \n %0x \n %0x \n %0x \n %0x",
&a,&b,&c,&d,&e,&f,&g,&h);
return 0;
}
Das Ergebnis ist das Folgende. Beachten Sie, dass zwischen jeder int-Adresse ein Unterschied von 4 Byte besteht. Zwischen dem letzten int und dem langen int besteht jedoch ein Unterschied von 12 Byte:
Hello, World!
The addresses are:
da54dcac
da54dca8
da54dca4
da54dca0
da54dc9c
da54dc98
da54dc94
da54dc88
int
afterh
in den Quellcode ein. Der Compiler kann es vorher in die Lücke setzenh
.sizeof
Funktion.printf("size: %d ", sizeof(long));
%x
. Glücklicherweise funktioniert es auf Ihrer Plattform ordnungsgemäß, Zeigerargumente mit einer erwartetenunsigned int
Formatzeichenfolge zu übergeben, aber Zeiger und Ints sind in vielen ABIs unterschiedlich groß. Verwenden Sie%p
Zeiger in portablen Code zu drucken. (Es ist leicht vorstellbar, dass Ihr Code die oberen / unteren Hälften der ersten 4 Zeiger anstelle der unteren Hälfte aller 8 druckt.)%zu
. @yoyo_fun zum Drucken von Adressen verwenden%p
. Die Verwendung des falschenAntworten:
Es dauerte nicht 12 Bytes nehmen, es dauerte nur 8 jedoch die Standard - Ausrichtung für ein 8 Byte langen int auf dieser Plattform ist 8 Byte. Aus diesem Grund musste der Compiler das lange int an eine durch 8 teilbare Adresse verschieben. Die "offensichtliche" Adresse da54dc8c ist nicht durch 8 teilbar, daher die Lücke von 12 Byte.
Sie sollten dies testen können. Wenn Sie ein weiteres int vor dem long hinzufügen, so dass es 8 davon gibt, sollten Sie feststellen, dass das long int ohne Verschiebung in Ordnung ist. Jetzt sind es nur noch 8 Bytes von der vorherigen Adresse.
Es ist wahrscheinlich erwähnenswert, dass Sie sich, obwohl dieser Test funktionieren sollte, nicht darauf verlassen sollten, dass die Variablen auf diese Weise organisiert werden. AC Compiler darf alle möglichen irren Dinge tun, um zu versuchen, dass Ihr Programm schnell ausgeführt wird, einschließlich der Neuordnung von Variablen (mit einigen Einschränkungen).
quelle
Dies liegt daran, dass Ihr Compiler einen zusätzlichen Abstand zwischen den Variablen generiert, um sicherzustellen, dass sie im Speicher korrekt ausgerichtet sind.
Bei den meisten modernen Prozessoren ist der Zugriff auf einen Wert, dessen Adresse ein Vielfaches seiner Größe hat, effizienter. Wenn es
h
an der ersten verfügbaren Stelle platziert worden wäre, wäre seine Adresse 0xda54dc8c, was kein Vielfaches von 8 ist, und daher weniger effizient zu verwenden gewesen. Der Compiler weiß darüber Bescheid und fügt zwischen den letzten beiden Variablen ein wenig ungenutzten Speicherplatz hinzu, um sicherzustellen, dass dies geschieht.quelle
Ihr Test testet nicht unbedingt, was Sie denken, da die Sprache nicht verpflichtet ist, die Adresse einer dieser lokalen Variablen miteinander in Beziehung zu setzen.
Sie müssten diese als Felder in eine Struktur einfügen, um auf die Speicherzuordnung schließen zu können.
Lokale Variablen müssen den Speicher nicht auf bestimmte Weise nebeneinander teilen. Der Compiler kann beispielsweise eine temporäre Variable an einer beliebigen Stelle im Stapel einfügen, die sich zwischen zwei dieser lokalen Variablen befinden kann.
Im Gegensatz dazu ist es nicht zulässig, eine temporäre Variable in eine Struktur einzufügen. Wenn Sie also stattdessen die Adressen von Strukturfeldern drucken, vergleichen Sie die beabsichtigten Elemente, die aus demselben logischen Speicherbereich (der Struktur) zugewiesen wurden.
quelle