Ist es zulässig, ein Element einer Struktur zu überschreiben, um ein anderes zu sehen?

8

Gegeben der folgende erfundene Beispielcode:

%Vor%

Die Ausgabe des Programms ist 10.

Obwohl dies nicht die beste Programmierpraxis ist, funktioniert das. Ist dies jedoch ein Artefakt des Compilers und der Plattform, oder ist das ein gesetzlicher Code? (d. h. durch den C-Standard definiert?)

Selbst wenn das Ergebnis nicht garantiert 10 ist, gibt es jemals eine Instanz, wo dies "illegal" wäre (d. h. Schreiben in den Speicher, den ich nicht "besitze")?

    
David Pfeffer 13.12.2011, 14:35
quelle

4 Antworten

4

EDIT: Wie von anderen gesagt, ist dies nicht legal, da es zu undefiniertem Verhalten führt. Ich habe diesen Satz aus meiner Antwort entfernt.

Dies kann zu undefiniertem Verhalten führen. Sie haben in der Struktur abc einen Speicherblock von 10 ints Länge zugewiesen, so dass die Indizierung in den 5. (6.) Eintrag Sie zu y [0] führt, wie Sie in diesem speziellen Fall bemerkt haben.

Wo Probleme auftreten können, ist, wenn der C-Compiler die Struktur auf eine Weise packt, die Sie nicht erwarten. Dies wird Datenpackung oder Bitausrichtung genannt. Wenn der Computer von Ihrer Datenstruktur aus auf Speicher zugreifen möchte, versucht er dies in gleichmäßigen Abschnitten für die gesamte Struktur. Nehmen wir ein Beispiel:

%Vor%

Was erwarten Sie von der Größe dieser Struktur? Ein Int ist 32 Bits und ein Zeichen ist 8 Bits, so dass die Gesamtgröße 32 + 8 + 32 = 72 Bits sein sollte. Sie werden jedoch feststellen, dass diese Struktur auf vielen Systemen tatsächlich 96 Bit groß ist. Der Grund dafür ist, dass Char b am Ende mit weiteren 24 Bits gepackt wird, um einen Standard-Offset zwischen den Variablen beizubehalten.

Dies kann sehr verwirrend sein, wenn Sie eine Struktur an zwei verschiedenen Orten deklarieren, und eines wird gepackt, während das andere wegen der Optionen für die Kompilierung oder der Konfiguration nicht kompiliert wird.

Suchen Sie nach Bit-Packing und Datenausrichtung oder Bitausrichtung für weitere Informationen.

    
Brett McLain 13.12.2011, 14:44
quelle
12

Nein, es ist weder legal noch garantiert, dass es funktioniert. Der Compiler könnte der Struktur Auffüllung hinzufügen, um die Ausrichtung zu unterstützen, abhängig von der Architektur usw.

Bearbeiten: Um einige Dinge in diesen Kommentaren zusammenzufassen und zu verdeutlichen ...

Ich glaube, dass Sie die Erinnerung dort "besitzen", denn wie edA-qa mort-ora-y zeigt, muss memcpy () einer Struktur funktionieren. Wo dies jedoch ausdrücklich garantiert ist, bin ich mir nicht sicher.

Das heißt, undefiniertes Verhalten ist etwas, das um jeden Preis vermieden werden sollte. Was ein Programm mit undefiniertem Verhalten tun kann, kann sich zwischen zwei separaten Läufen desselben Codes im Abstand von fünf Sekunden ändern. Es kann zu subtiler Speicherbeschädigung in Ihrem Programm, einem segfault oder einem fehlerfreien Ablauf kommen, aber es gibt keinen Grund, jemals Code zu verwenden, der auf undefiniertem Verhalten beruht.

    
Dan Fego 13.12.2011 14:37
quelle
5

Dies ist undefiniertes Verhalten - Sie sind in diesem Fall (un) glücklich. Darüber hinaus gibt es (abgesehen von dem erwähnten Padding-Problem) das Problem der Wartbarkeit - es ist unglaublich fragil - was ist, wenn jemand etwas dazwischen zwängt. Ich bin sicher, dass es ein künstliches Beispiel ist, aber die Empfehlung ist - tu es nicht.

    
Nim 13.12.2011 14:38
quelle
3

Technisch ist das Verhalten nicht definiert.

  

Obwohl dies nicht die beste Programmierpraxis ist, funktioniert das.

Undefiniertes Verhalten bedeutet, dass alles passieren kann, einschließlich was Sie erwarten. Es könnte durchaus auf andere Implementierungen abstürzen.

    
Prasoon Saurav 13.12.2011 14:37
quelle

Tags und Links