2013-01-24 16 views
5

Bei dem Versuch, ein Problem zu debuggen Ich habe Speex verwenden, bemerkte ich, dass es (na ja, nicht nur speex, aber einige Beispiel-Code als auch) macht folgendes:Wirf eine Struktur T * auf ein strukturiertes C * undefiniertes Verhalten, wenn Ts erstes Feld ein C ist?

  • einen Zeiger von ein bis EncState Initialisierungsfunktion
  • Besetzung, die Zeiger auf einen Zeiger Hohlraum
  • Shop der Hohlraum Zeiger
  • (anderswo)
  • den Hohlraum Zeiger auf einen Zeiger zu gieße SpeexMode auf Zeiger
  • die Zeiger dereferenzieren

kommt es vor, so dass die Definition der EncState mit einem Feld des Typ SpeexMode * beginnt, und so ist die ganzzahligen Werte von einem Zeiger auf das erste Feld und einen Zeiger auf die Struktur passieren, das gleiche sein . Die Dereferenzierung funktioniert zur Laufzeit.

Aber ... erlaubt die Sprache das tatsächlich? Kann der Compiler tun, was er will, wenn er das kompiliert? Wirf eine Struktur T * in ein strukturiertes C * undefiniertes Verhalten, wenn Ts erstes Feld ein C ist?

+0

Auch ein Duplikat von [Struct Zeigerkompatibilität] (http://stackoverflow.com/questions/8702713/struct-pointer-compatibility) – netcoder

+0

Es ist technisch UB, ja, wegen der strengen Aliasing-Regel. Der bevorzugte Weg besteht normalerweise darin, eine Vereinigung mit Mitgliedern beider Typen zu verwenden. – netcoder

Antwort

7

Vom C11 Standard:

(C11 §6.7.2.1.15: „Ein Zeiger auf ein Strukturobjekt, in geeigneter Weise umgewandelt, weist auf seinen Anfangsglied ... und vice versa Es kann. unbenannte Polsterung sein innerhalb als Strukturobjekt, aber nicht an seinem Anfang. ")

Was bedeutet, dass das Verhalten, das Sie sehen, ist erlaubt und garantiert.

+1

Es bricht jedoch die strenge Aliasing-Regel. – netcoder

+0

@netcoder True, wenn es in diesem Fall zu Problemen führt, ist jedoch unklar. – pmr

+0

+1 Konzise und klare Antwort ... Ich könnte als Kommentar hinzufügen, dass Sie viele viele Beispiele für diese Art der Typumwandlung im GObject-Framework finden können – Rerito