it-swarm.com.de

Warum benötigt ein langer int auf einigen Computern 12 Bytes?

Nach dem Kompilieren dieses Codes auf meinem Computer ist mir etwas Seltsames 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
26
yoyo_fun

Es dauerte nicht 12 Bytes, sondern nur 8. Der Standardwert Ausrichtung für ein 8 Byte langes int auf dieser Plattform beträgt jedoch 8 Bytes. Daher musste der Compiler das lange int an eine Adresse verschieben, die durch 8 teilbar ist. Die "offensichtliche" Adresse da54dc8c ist nicht durch 8 teilbar, daher die 12-Byte-Lücke.

Sie sollten dies testen können. Wenn Sie vor dem Long ein weiteres Int hinzufügen, sodass es 8 davon gibt, sollten Sie feststellen, dass das Long Int ohne Bewegung in Ordnung ausgerichtet wird. 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. Ein C-Compiler darf alle möglichen funky Dinge tun, um zu versuchen, Ihr Programm schnell laufen zu lassen, einschließlich der Neuordnung von Variablen (mit einigen Einschränkungen).

81
Alex

Dies liegt daran, dass Ihr Compiler zusätzliche Auffüllungen zwischen Variablen generiert, um sicherzustellen, dass diese im Speicher korrekt ausgerichtet sind.

Wenn ein Wert auf den meisten modernen Prozessoren eine Adresse hat, die ein Vielfaches seiner Größe beträgt, ist der Zugriff effizienter. Wenn es h an der ersten verfügbaren Stelle platziert hätte, wäre seine Adresse 0xda54dc8c gewesen, was kein Vielfaches von 8 ist, und wäre daher weniger effizient zu verwenden gewesen. Der Compiler weiß davon und fügt zwischen den letzten beiden Variablen etwas unbenutzten Speicherplatz hinzu, um sicherzustellen, dass dies geschieht.

9
Jules

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 etwas über die Speicherzuordnung ableiten zu können.

Lokale Variablen sind nicht erforderlich, um den Speicher auf bestimmte Weise nebeneinander zu teilen. Der Compiler kann beispielsweise irgendwo im Stapel eine temporäre Variable einfügen, die zwischen zwei dieser lokalen Variablen liegen 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 Speicherfutter (der Struktur) zugewiesen wurden.

2
Erik Eidt