Frage

Anstatt einen tatsächlichen Zeiger auf einen Wert zu senden, wird der Wert auf einen Zeiger gegossen. Ich fand diese Beispiele in der GUI-Schnittstelle Code eines GTK-Programm.

g_signal_connect (pastebutton[pane],
                  "clicked",
                  G_CALLBACK(on_paste_button_pressed),
                  (void*)((long)pane<<4));

Im obigen Beispiel, ich beziehe mich auf die letzten Parameter von g_signal_connect. Wenn on_paste_button_pressed von GTK2 genannt wird, on_paste_button_pressed wirft die user_data void-Zeiger zurück in etwa so:

int pane = ((long)user_data) >> 4;

Eigentlich hinzugefügt, ich dieses spezielle Beispiel auf den Code, aber ich basiert es auf dem, was schon da war. Ich fügte hinzu, die Bit-Verschiebung um zu vermeiden, Warnungen über Gießen. Das Programm selbst hat vier Scheiben eines ganze Reihe von Widgets enthalten, das Kopieren und Einfügen von Schaltflächen können Sie alle Werte von einem Fensterbereich auf einem anderen kopieren.

Ist diese Art und Weise einen Wert in eine Zeigeradresse des Gießens oft verwendet, und gibt es Gründe, warum dies sollte nicht verwendet werden?

Bearbeiten

Die Besetzung aus einer ganzen Zahl auf einen void-Zeiger kann auch wie so erreicht werden:

void* void_ptr = some_int - NULL;
War es hilfreich?

Lösung

Es ist verwendet . Es ist verwendet recht häufig, wenn es funktioniert, was erforderlich ist.

Einen Grund es nicht zu benutzen ist, dass theoretisch Zeigergröße kleiner sein könnte als die Source-Integer-Größe.

Ein weiterer Grund, es nicht zu benutzen ist, dass es nur ein Stück von ganzzahligen Daten an die Callback passieren lässt. Wenn in der Zukunft benötigen Sie ein weiteres Stück von Daten (oder Wechsel zu einem nicht ganzzahligen) hinzuzufügen, müssen Sie ausfindig zu machen und jeden einzelnen Ort zu umschreiben, wo der Rückruf Zugriff auf die übergebenen Daten macht. Also, wenn es eine Chance, dass Sie die Daten in der Zukunft erweitern müßten, ist es besser, einen struct zu schaffen (auch wenn es zu diesem Zeitpunkt nur eine einzige int hält) und einen Zeiger auf diesen struct passieren.

Aber wenn Sie sicher sind, dass Sie nie etwas anderes als diese einzelne ganze Zahl passieren müssen und dass Ihre ganze Zahl passt in eine void *, dann ist diese Technik nicht in irgendeiner Weise gebrochen.

PS Pedantisch gesprochen, weder C noch C ++ erscheint die Hin- und Rückgarantie für Integer-to-Lücke haben * -bis-Integer-Umwandlung, dh sie nicht garantieren, dass es funktionieren wird und die Wiederherstellung Original-Integralwert.

Andere Tipps

Sie sollten Makros GINT_TO_POINTER () und GPOINTER_TO_INT (), um Guss zwischen Zeiger und Zahlen.

glib: Typumwandlung Makros

Gießen eine ganze Zahl auf einen Zeiger wird verwendet, um einen Wert für-Wert zu übergeben. Dies ist die bevorzugte Art und Weise, wenn Sie einen Nebenreferenzparameter brauchen, da der Compiler dann braucht nicht den Zeiger dereferenzieren.

Die Bit-Verschiebung ist eine schlechte Idee, weil es dazu führen, überläuft kann.

Für wirklich portablen Code, sollten Sie intptr_t als Integer-Typen verwenden, weil es gut in einen Zeiger passen.

Es tut Verwendung in dieser Art von Fällen sehen, ja. Es funktioniert auf vielen Plattformen, könnte aber scheitern, weil eine beliebige ganze Zahl nicht immer ein gültiger Zeigerwert ist, wenn die Verschiebung Sie, dass umgehen tun soll. Es ist auch möglich, dass ein Zeiger kann alle Werte nicht festhalten, dass eine ganze Zahl kann; Dies wäre der Fall, wenn Sie einen 64-Bit-long auf einer Plattform verwenden, wo Zeiger 32 Bits sind, und natürlich, da Sie den Wert verschieben, könnte es auch, wenn Zeiger und Zahlen nicht die gleiche Größe haben. Wenn Sie diesen Trick verwenden möchten, sollten Sie wahrscheinlich sizeof (void*) gegen die Größe des Integer-Typs überprüfen Sie verwenden, und zur Laufzeit Prüfung gegen den tatsächlichen Wert, wenn der Zeiger nicht groß genug ist. Es ist wahrscheinlich nicht wert dieses vollständig tragbar zu machen, so dass Sie einen tatsächlichen Zeiger auf Plattformen verwenden würden, wenn diese benötigt wird, also entweder beschränken Sie sich auf Plattformen, auf denen dieser Trick funktioniert oder den Trick ganz aufgeben.

ich es ganz gut finden. Ich habe keine Statistiken über Benutzungshäufigkeit, aber egal Sie wirklich?

Ich bin sicher, dass ich nicht verstehen, wie Bitverschiebung hilft, though.

Es wird verwendet, aber es ist keineswegs tragbar, so dass Sie vorsichtig sein.

Der C-Standard schreibt nicht vor, dass die Zeigertypen zumindest so viele Bits wie Integer-Typen, so dass Sie nicht immer in der Lage sein können, es zu tun.

Aber ich kann mich nicht erinnern jeder Plattform, in der Zeiger haben wirklich war kleiner als ganze Zahlen, so dass Sie wahrscheinlich sicher sind (trotz technisch nicht sicher ist).

Der einzige Grund, warum ich glaube, dass das Casting für da sein kann, ist die Möglichkeit der Ausrichtung Warnungen zu entfernen. Abschnitt 6.3.2.3 des C1x Entwurf heißt es:

  

Eine Ganzzahl kann auf jeden Zeigertyp umgewandelt werden. Außer wie zuvor angegeben, die   Ergebnis ist die Implementierung definiert, möglicherweise nicht richtig ausgerichtet werden, weisen möglicherweise nicht für eine   Entität der genannten Art, und könnte eine Falle Darstellung sein.

Dies ist aus dem C-FAQ:

F: Wie ganze Zahlen umgewandelt werden und von Zeigern? Kann ich vorübergehend kehrt eine ganze Zahl in einen Zeiger oder umge stopfen?

A: Es ist einmal, wurde sichergestellt, dass ein Zeiger auf eine ganze Zahl umgewandelt werden könnte (obwohl man nie, ob ein int wußte oder ein lange erforderlich sein könnte), und dass eine ganze Zahl in einen Zeiger umgewandelt werden könnte, und dass ein Zeiger unverändert blieb, wenn sie einen (groß genug) integer umgewandelt und wieder zurück, und dass die Umsätze (und jede Abbildung) wurden `` die überraschend, sein sollen, der die Adressierung Aufbau der Maschine kennen. ‚‘ Mit anderen Worten: gibt es einige Präzedenzfall und Unterstützung für integer / Zeiger Konvertierungen, aber sie haben immer maschinenabhängig gewesen und daher nicht portierbar. Explizite Abgüsse immer erforderlich ist (obwohl frühen Compiler selten beschwerten wenn Sie sie links).

Der ANSI / ISO C Standard, um sicherzustellen, dass C weit implementierbar ist, hat diese früheren Garantien geschwächt. Pointer-to-integer und integer-zu-Zeiger-Conversions sind die Implementierung definiert (siehe Frage 11.33), und es gibt nicht mehr eine Garantie, dass Zeiger auf ganze Zahlen und zurück überführt werden können, ohne Änderung.

Zeiger in ganzen Zahlen Erzwingen oder ganze Zahlen in Zeiger, hat nie gute Praxis. Wenn Sie einen allgemeinen Slot benötigen, die entweder Art von Daten halten können, ist eine Vereinigung eine viel bessere Idee.

Siehe auch Fragen 4.15, 5.18 und 19.25.

Referenzen: K & R1 Sec. A14.4 p. 210 K & R2 Sec. A6.6 p. 199 ISO Sec. 6.3.4 Rationale Sec. 3.3.4 H & S Sec. 6.2.3 p. 170, Sec. 6.2.7 pp. 171-2

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top