Verstößt der folgende Code gegen striktes Aliasing?

int a = 0;
*((int *)((char *)&a)) = 1;

Warum nicht? , weil wir den Zeiger von int a mit int * dereferenzieren, was legitim ist

Warum ja? , weil wir das char * in int * umwandeln und es dereferenzieren (das int *), was als strikte Aliasing-Verletzung erscheint

1
izac89 19 Jän. 2019 im 18:45

3 Antworten

Beste Antwort

Dieser Code ist gültig. Es ist zulässig, zwischen zwei Objektzeigertypen und zurück zu konvertieren, sofern keine Ausrichtungsprobleme vorliegen, und das Konvertieren in ein char * ist explizit zulässig, um auf eine Objektdarstellung zuzugreifen (d. H. Die einzelnen Bytes zu lesen).

Abschnitt 6.3.2.3p7 des C-Standards Staaten:

Ein Zeiger auf einen Objekttyp kann in einen Zeiger auf einen anderen Objekttyp konvertiert werden. Wenn der resultierende Zeiger für den referenzierten Typ nicht korrekt ausgerichtet ist, ist das Verhalten undefiniert. Andernfalls wird das Ergebnis bei erneuter Konvertierung mit dem ursprünglichen Zeiger verglichen. Wenn ein Zeiger auf ein Objekt in einen Zeiger auf einen Zeichentyp konvertiert wird, zeigt das Ergebnis auf das niedrigste adressierte Byte des Objekts. Aufeinanderfolgende Inkremente des Ergebnisses bis zur Größe des Objekts ergeben Zeiger auf die verbleibenden Bytes des Objekts.

Da Sie von int * nach char * und dann zurück nach int * konvertieren, gibt es hier keine strengen Aliasing-Verstöße.

1
dbush 19 Jän. 2019 im 15:54

Die strengen Aliasing-Regeln berücksichtigen keine Zwischenbesetzungen. Sie kümmern sich nur um den Typ des Zeigers, der letztendlich für den Zugriff auf ein Objekt verwendet wird, und den ursprünglichen Typ des Objekts selbst (technisch gesehen der "effektive Typ", aber das ist momentan nicht wichtig).

In Ihrem Beispielcode nehmen Sie die Adresse eines int. Das Ergebnis hat den Typ int *. Sie setzen diesen Zeiger auf char *, Sie setzen ihn erneut auf int * und erst dann dereferenzieren Sie ihn. Der Typ des im Zugriff verwendeten Zeigers ist int * und der Typ des Objekts, auf das verwiesen wird, ist int, sodass die strengen Aliasing-Regeln kein Problem darstellen.

Sie haben Recht, dass die strengen Aliasing-Regeln in Bezug auf char asymmetrisch sind. Dies ist jedoch nur dann von Bedeutung, wenn entweder der Typ des Objekts selbst char oder der Typ des im Zugriff verwendeten Zeigers {{ X2}}:

char x[sizeof(int)] = { 0 };
*(int *)x = 1;  // undefined behavior

int y = 1234;
*(char *)y = 0; // valid; value of y becomes unspecified

Theoretisch kann eine Umwandlung zwischen zwei Zeigertypen Informationen verlieren, jedoch nicht, wenn von einem anderen Typ in char * und wieder zurück umgewandelt wird. Dies ist auch nur auf Computern relevant, auf die Sie heutzutage sehr unwahrscheinlich stoßen. Ich kann mich nicht an ein Beispiel erinnern.

2
zwol 19 Jän. 2019 im 15:55

Nein, es ist keine Verletzung.

weil wir char * in int * umwandeln

Ihnen fehlt der Teil, von dem das char *, das Sie erwähnt haben, tatsächlich ein int * war. Somit wird schließlich der Zugriff auf einen int Typ über einen Zeiger auf int hergestellt - dies ist vollkommen gültig.

1
Sourav Ghosh 19 Jän. 2019 im 15:54