Alternative Art der Berechnung der Größe eines Typs mit Zeigerarithmetik

8

Ist der folgende Code 100% portabel?

%Vor%

P.S : Die Frage dient nur dem Lernen. Also gib bitte keine Antworten wie Use sizeof() etc

    
Prasoon Saurav 02.08.2010, 10:51
quelle

9 Antworten

13

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 .

    
Nordic Mainframe 02.08.2010, 11:13
quelle
4

&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.

    
Kirill V. Lyadvinsky 02.08.2010 10:56
quelle
2

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.

    
h2stein 02.08.2010 11:19
quelle
2

Es ist nicht 100% tragbar aus folgenden Gründen:

  1. Bearbeiten: Am besten verwenden Sie int a[1]; und dann wird a+1 definitiv gültig.
  2. & amp; a ruft undefiniertes Verhalten bei Objekten der Registerspeicherklasse auf.
  3. Bei Ausrichtungseinschränkungen, die größer oder gleich der Größe von int type sind, enthält size_of_int nicht die richtige Antwort.

Haftungsausschluss:

Ich bin unsicher, ob das obige für C ++ gilt.

    
Michael Foukarakis 02.08.2010 11:23
quelle
1

Warum nicht einfach:

%Vor%     
Paul Betts 02.08.2010 10:54
quelle
1

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)

    
Henk Holterman 02.08.2010 10:58
quelle
0

Ja, es gibt Ihnen das Äquivalent von sizeof(a) , aber verwenden Sie ptrdiff_t anstelle von size_t type.

    
wilx 02.08.2010 11:07
quelle
0

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.

    
Frank Bollack 02.08.2010 11:09
quelle
0

Der obige Code berechnet sizeof(int) portabel auf einer Zielplattform, aber letztere ist eine Implementierung definiert - Sie erhalten unterschiedliche Ergebnisse auf verschiedenen Plattformen.

    
sharptooth 02.08.2010 10:57
quelle

Tags und Links