Ist der folgende Code 100% portabel?
%Vor% P.S : Die Frage dient nur dem Lernen. Also gib bitte keine Antworten wie Use sizeof()
etc
Von ANSI-ISO-IEC 14882-2003, S.87 (c ++ 03):
"75) Eine andere Möglichkeit, sich dem Zeiger zu nähern Arithmetik konvertiert zuerst die Zeiger auf Zeichenzeiger (n): In Dieses Schema der Integralwert der Ausdruck hinzugefügt oder subtrahiert von der konvertierte Zeiger ist zuerst multipliziert mit der Größe des Objekts ursprünglich darauf hingewiesen, und die Der resultierende Zeiger wird zurück in konvertiert der ursprüngliche Typ. Für Zeiger Subtraktion, das Ergebnis der Unterschied zwischen dem Charakter Zeiger wird in ähnlicher Weise durch die geteilt ursprünglich angegebene Größe des Objekts zu. "
Dies deutet darauf hin, dass die Zeigerdifferenz gleich der Objektgröße ist.
Wenn wir die UB'ness entfernen, indem wir einen Zeiger auf einen Skalar a inkrementieren und a in ein Array verwandeln:
%Vor%Dann sieht das OK aus. Die Klauseln zu Ausrichtungsanforderungen stimmen mit der Fußnote überein, wenn Ausrichtungsanforderungen immer durch die Größe des Objekts teilbar sind.
UPDATE: Interessant. Wie die meisten von Ihnen wahrscheinlich wissen, erlaubt GCC eine explizite Ausrichtung auf Typen als Erweiterung. Aber ich kann OPs "sizeof" -Methode damit nicht brechen, weil GCC es nicht kompiliert:
%Vor% Die Nachricht lautet error: alignment of array elements is greater than element size
.
&a+1
führt zu einem undefinierten Verhalten gemäß dem C ++ Standard 5.7 / 5:
Wenn ein Ausdruck mit einem ganzzahligen Typ zu einem Zeiger hinzugefügt oder von ihm subtrahiert wird, hat das Ergebnis den Typ der Zeigeroperand. & lt; ... & gt; Wenn sowohl der Zeigeroperand als auch das Ergebnis auf Elemente desselben Arrayobjekts oder eines nach dem letzten Element des Arrayobjekts zeigen, darf die Auswertung keinen Überlauf erzeugen. Andernfalls ist das Verhalten nicht definiert.
&a+1
ist OK nach 5.7 / 4:
Für die Zwecke dieser Operatoren verhält sich ein Zeiger auf ein Nicht-Array-Objekt genauso wie ein Zeiger auf den ersten Element eines Arrays der Länge eins mit dem Typ des Objekts als Elementtyp.
Das bedeutet, dass 5,7 / 5 ohne UB angewendet werden kann. Und schließlich Bemerkung 75 von 5.7 / 6 als @Luther Blissett
in seiner Antwort erwähnt, dass der Code in der Frage gültig ist.
Im Produktionscode sollten Sie stattdessen sizeof
verwenden. Aber der C ++ Standard garantiert nicht, dass sizeof(int)
4 auf jeder 32-Bit-Plattform ergibt.
Nein. Dieser Code wird nicht auf allen Plattformen funktionieren. Zumindest theoretisch könnte es eine Plattform mit z.B. 24-Bit-Ganzzahlen (= 3 Bytes), aber 32-Bit-Ausrichtung. Solche Alignments sind nicht untypisch für (ältere oder einfachere) Plattformen. Dann würde Ihr Code 4 zurückgeben, aber sizeof (int) würde 3 zurückgeben.
Aber mir ist keine echte Hardware bekannt, die sich so verhält. In der Praxis funktioniert Ihr Code auf den meisten oder allen Plattformen.
Es ist nicht 100% tragbar aus folgenden Gründen:
int a[1];
und dann wird a+1
definitiv gültig. int
type sind, enthält size_of_int
nicht die richtige Antwort. Ich bin unsicher, ob das obige für C ++ gilt.
Wahrscheinlich ist die Implementierung definiert.
Ich kann mir ein (hypothetisches) System vorstellen, bei dem sizeof (int) kleiner ist als die Standardausrichtung.
Es sieht nur sicher aus, dass size_of_int >= sizeof(int)
Es gab eine Debatte über eine ähnliche Frage .
Siehe die Kommentare zu meiner Antwort zu dieser Frage für einige Hinweise, warum dies so ist ist nicht nur nicht portabel, sondern ist auch undefiniertes Verhalten nach dem Standard.
Der obige Code berechnet sizeof(int)
portabel auf einer Zielplattform, aber letztere ist eine Implementierung definiert - Sie erhalten unterschiedliche Ergebnisse auf verschiedenen Plattformen.
Tags und Links c c++ pointers casting portability