2013-09-05 6 views
6

In einem C-Programm habe ich eine StrukturWann ist es legal, mit einem Zeiger auf einen Zeiger in C zu tippen?

typedef struct { 
    void *payload; // opaque, real type known to callbacks 

     ... some stuff ... 
} MiddleMan; 

Um etwas Furnier von Typsicherheit zu schaffen könnte ich

CbData *get_cb_data(const MiddleMan *mm){ return mm->payload; } 
void set_cb_data(MiddleMan *mm, CbData *cbd){ mm->payload = cbd; } 

Getter und Setter erstellen Oder ich kann versuchen, es mit einem einzigen, Zeiger zu tun -basierte Accessor

CbData **cb_data(MiddleMan *mm){return (CbData**)&mm->payload;} 

Nun ist die zweite Lösung sieht dodgier als die erste, und es schränkt auch Benutzer auf nicht-const mm auch wenn sie o will nur lesen. Aber meine Frage ist, ob es überhaupt legal C ist?

Ich bin mir ziemlich sicher, dass Sie damit auf jeder Architektur, wo void* ist die gleiche Größe & Format wie CbData*. Aber kann jemand klar begründen, warum das überhaupt gilt (oder nicht)?

+1

Dies ist legal in C. 'void *' und 'CbData *' haben immer die gleiche Größe - beide sind Zeigertypen. Tut mir leid, aber ich verstehe nicht, warum es eine Frage zur Gültigkeit dieser '**' Implementierung gibt, die Sie oben geschrieben haben. –

+3

Auf einigen seltsamen Architekturen variiert die Größe der Zeiger je nachdem, auf was sie zeigen. 'void *' sollte groß genug sein, um alle Möglichkeiten abzudecken, aber 'CbData *' kann kleiner sein, abhängig davon, was 'CbData' eigentlich ist. –

+0

können Sie bitte einige Beispiele dieser seltsamen Architekturen geben? Wirklich neugierig. –

Antwort

4

Im Allgemeinen sollten Sie das nicht tun. A void** kann die unterschiedliche Ausrichtungsanforderung mit CbData** haben. Ein expliziter Cast kann die unterschiedliche Adresse erzeugen.

C Standard 6.2.5.27:

Ein Zeiger für ungültig zu erklären soll die gleiche Darstellung und Ausrichtung Anforderungen als ein Zeiger auf ein Zeichen type.39 haben) Ähnlich Zeiger auf qualifizierte oder unqualifizierte Versionen kompatibel Typen müssen die gleichen Darstellung und Ausrichtung Anforderungen haben. Alle Zeiger auf Strukturtypen müssen die gleiche Darstellung und Ausrichtung haben wie die Anforderungen. Alle Zeiger auf Union-Typen müssen gleiche Darstellungs- und Ausrichtungsanforderungen haben. Zeiger zu anderen Typen müssen nicht die gleiche Darstellung oder Ausrichtung Anforderungen haben.

+0

jedoch 6.3.2.3 sagt: 'Ein Zeiger auf void kann in oder von einem Zeiger zu einem unvollständigen oder Objekt Typ konvertiert werden. Ein Zeiger auf einen unvollständigen oder Objekttyp kann in einen Zeiger auf void und wieder zurück konvertiert werden; das Ergebnis soll dem ursprünglichen Zeiger entsprechen. "... würde das hier nicht gelten? – msam

+0

Bis jetzt klingt das korrekt, aber ich warte auf andere Meinungen, bevor ich es akzeptiere. Da 'void *' der allgemeinste Zeigertyp ist, wird 'void **' die strengste Ausrichtung haben, und daher wird die Umwandlung in '(CbData **)' eine reine Neuinterpretation sein. Meine Vermutung ist, dass das Ding illegal ist, aber selbst auf den seltsamsten Architekturen funktioniert. –

+0

@msam, die über explizite Typkonvertierungen zwischen Zeigerwerten spricht, während ich auf die Adresse dieser Zeiger punning bin.Deshalb sind die Dinge nicht klar. –

Verwandte Themen