Strict aliasing bezieht sich auf, wenn ein Zeiger in einen anderen Zeigertyp konvertiert wird, nach dem auf den Inhalt zugegriffen wird. Strenges Aliasing bedeutet, dass die beteiligten spitzen Typen kompatibel sein müssen. Das trifft hier nicht zu.
Es gibt jedoch den Begriff Pointer Aliasing, was bedeutet, dass zwei Zeiger auf denselben Speicher verweisen können. Der Compiler darf nicht davon ausgehen, dass dies hier der Fall ist. Wenn es Optimierungen wie die von Ihnen beschriebenen durchführen möchte, müsste es möglicherweise Maschinencode hinzufügen, der die Zeiger miteinander vergleicht, um festzustellen, ob sie identisch sind oder nicht. Was an sich die Funktion etwas langsamer machen würde.
Um den Compiler zu helfen, solchen Code zu optimieren, können Sie die Zeiger als restrict
deklarieren, was dem Compiler mitteilt, dass der Programmierer garantiert, dass die Zeiger nicht auf den gleichen Speicher zeigen.
Ihre Funktion mit gcc -O3
Ergebnisse in dieser Maschinencode kompiliert:
0x00402D09 mov $0x1,%edx
was im Grunde bedeutet, dass die ganze Funktion ersetzt wurde (inlined) mit "a.x auf 1 gesetzt".
Aber wenn ich Ihre Funktion als
int test_func(A* restrict a, int* restrict x)
{
a->x = 0;
*x = 1;
return a->x;
}
neu schreiben und kompilieren mit gcc -O3
, tut es 0 zurück, weil ich jetzt den Compiler gesagt haben, dass a->X
und x
nicht auf dem gleichen Speicher zeigen, so kann es Nehmen Sie an, dass *x = 1;
das Ergebnis nicht beeinflusst und überspringen Sie die Zeile *x = 1;
oder Sequenz vor der Zeile a->x = 0;
.
Der optimierte Maschinencode der Restricted-Version überspringt tatsächlich den gesamten Funktionsaufruf, da er weiß, dass der Wert gemäß Ihrer Initialisierung bereits 0 ist.
Dies ist natürlich ein Fehler, aber der Programmierer ist dafür verantwortlich, für die sorglose Verwendung von restrict
.
Ich denke nicht, weil dies der Zweck des Schlüsselwortes ['restrict'] (https://en.wikipedia.org/wiki/Restrict) in C. – Stargateur
ist Ich dachte, dass * strikter Aliasing * auf die verwiesen Fall der Konvertierung zwischen Zeigertypen, unter der Annahme, dass die Typen von gleicher Größe waren. Zum Beispiel das Konvertieren von 'int *' nach 'float *' auf einer Plattform mit 'sizeof int == sizeof float'. Und ich dachte, dass diese Einschränkung auf die Tatsache zurückzuführen ist, dass jede Plattform unterschiedliche Ausrichtungsanforderungen hat, was in bestimmten Szenarien zu undefiniertem Verhalten führen kann. Ich sehe nichts davon in deinem Code. –
Als Faustregel kann man sagen, dass es nur dann eine "strikte Alias-Verletzung" geben kann, wenn Sie einen Zeiger auf einen anderen Typ setzen oder ihn in 'void *' und dann in einen anderen Typ konvertieren. Hier in Ihrem Fall sind alle Typinformationen für den Compiler vorhanden, so dass keine Probleme auftreten dürfen. –