Verwendung von intptr_t anstelle von void*?

Lesezeit: 4 Minuten

Benutzer-Avatar
Gepard

Ist es eine gute Idee zu verwenden intptr_t als Allzweckspeicher (zum Halten von Zeigern und ganzzahligen Werten) statt void*? (Wie hier zu sehen: http://www.crystalspace3d.org/docs/online/manual/Api1_005f0-64_002dBit-Portability-Changes.html)

Denn was ich schon gelesen habe:

  • int -> void* -> int Hin- und Rückfahrt ist nicht garantiert, den ursprünglichen Wert beizubehalten; ich vermute int -> intptr_t -> int Wird besorgt
  • Zeigerarithmetik auf beiden void* und intptr_t erfordert Würfe, also bekommt hier keiner einen Vorteil
  • void* bedeutet weniger explizite Umwandlungen beim Speichern von Zeigern, intptr_t bedeutet weniger Casts beim Speichern von Integer-Werten
  • intptr_t erfordert C99

Was muss ich noch beachten?

  • Nein. (Wenn es so wäre, hätten sie einfach die Semantik von intptr_t hinzugefügt void*)

    – Billy ONeal

    29. Februar 2012 um 2:34 Uhr

  • Der Beitrag fragt “(to hold pointers and integer values)”, diskutiert dann aber nur int, void * und intptr_t. Wie uintmax_t, size_t, long longetc. sind auch Integer-Typen, klingt so, als ob es bei der Frage nur um Objektzeiger geht, intptr_t und int Typen.

    – chux – Wiedereinsetzung von Monica

    28. Januar 2016 um 23:11 Uhr

Benutzer-Avatar
Keith Thompson

Ist es eine gute Idee zu verwenden intptr_t als Allzweckspeicher (zum Halten von Zeigern und ganzzahligen Werten) statt void*?

Nein.

intptr_t ist nicht garantiert vorhanden. Erstens wurde es, wie Sie bemerken, in C99 eingeführt. Zweitens müssen Implementierungen keinen ganzzahligen Typ haben, der groß genug ist, um konvertierte Zeigerwerte ohne Informationsverlust zu halten.

Konvertieren ein int zu intptr_t und zurück ist unwahrscheinlich Informationen zu verlieren, aber dafür gibt es keine wirkliche Garantie intptr_t ist breiter als int.

Wenn Sie Zeigerwerte speichern möchten, speichern Sie sie in Zeigerobjekten. Dafür sind Zeigerobjekte da.

Jeder Zeiger auf ein Objekt oder einen unvollständigen Typ kann konvertiert werden void* und wieder zurück ohne Informationsverlust. Es gibt keine solche Garantie für Zeiger auf Funktionen – aber jeder Zeiger-auf-Funktion-Typ kann ohne Informationsverlust in jeden anderen Zeiger-auf-Funktion-Typ und zurück konvertiert werden. (Ich beziehe mich auf den C-Standard; ich denke, POSIX bietet einige zusätzliche Garantien.)

Wenn Sie entweder eine Ganzzahl oder einen Zeigerwert im selben Objekt speichern möchten, sollten Sie als Erstes Ihr Design überdenken. Wenn Sie dies bereits getan haben und zu dem Schluss gekommen sind, dass Sie dies wirklich tun möchten, sollten Sie die Verwendung einer Union in Betracht ziehen (und sorgfältig verfolgen, welche Art von Wert Sie zuletzt gespeichert haben).

Es gibt APIs, die a verwenden void* Argument, um die Übergabe beliebiger Daten zu ermöglichen; siehe zum Beispiel die POSIX pthread_create() Funktion. Dies kann missbraucht werden, indem ein ganzzahliger Wert an gecastet wird void* aber es ist sicherer, die zu passieren die Anschrift eines Integer-Objekts.

  • Bitte erweitern Sie auf “unwahrscheinlich Informationen zu verlieren”. intptr_t macht einen Round-Trip einen Zeiger auf einen der Vergleiche gleichermaßen – ist dieses potenziell nicht-dasselbe-Bit-Muster der Informationsverlust Ihres Kommentars.

    – chux – Wiedereinsetzung von Monica

    28. Januar 2016 um 20:55 Uhr

  • @chux: Wie gesagt, dafür gibt es keine Garantie intptr_t ist breiter als int (obwohl ich keine Implementierung kenne, wo dies nicht der Fall ist). Wenn zum Beispiel intptr_t ist 32 Bit und int ist 64 bit, dann wandelt man an int zu intptr_t und zurück zu int könnten Informationen verlieren. Insbesondere, wenn die int Der Wert liegt außerhalb des Bereichs von intptr_tergibt die erste Konvertierung ein implementierungsdefiniertes Ergebnis.

    – Keith Thompson

    28. Januar 2016 um 22:54 Uhr

  • Entschuldigung, lesen Sie die Antwort falsch als “Konvertieren von a Zeiger zu intptr_t und zurück ist unwahrscheinlich, dass Informationen verloren gehen … “. Mein Kommentar basierte auf diesem Gedanken. Stimmen Sie der Seltenheit des zu int/intptr_t Ausgaben.

    – chux – Wiedereinsetzung von Monica

    28. Januar 2016 um 23:04 Uhr

Benutzer-Avatar
Perrie

Nein, es kann nicht garantiert werden, dass ein bestimmter Typ sowohl Zeiger als auch ganze Zahlen vernünftig speichern kann, und außerdem macht es Ihren Code unübersichtlich. Es gibt einen besseren Weg.

Wenn Sie eine Ganzzahl und einen Zeiger im selben Objekt speichern möchten, besteht die saubere und portable Methode darin, eine Union zu verwenden:

union foo {
   int integer_foo;
   void *pointer_foo;
};

Dies ist tragbar und ermöglicht es Ihnen, beide Arten von Dingen in der Größe des Speichers aufzubewahren, die für den größeren der beiden erforderlich ist. Es funktioniert garantiert immer.

  • Tun int und void* haben eine gemeinsame Anfangsfolge in Bezug auf das Layout? Ansonsten ist dies nicht tragbar, du bist nicht erlaubt, beide Mitglieder auf einmal zu speichern und das ist absolut nicht garantiert “immer funktioniert”.

    – Leichtigkeitsrennen im Orbit

    8. Februar 2014 um 17:39 Uhr

  • @LightnessRacesinOrbit Ich glaube nicht, dass er behauptet hat, dass zwei Werte gleichzeitig darin gespeichert werden könnten. “beide” bedeutet, dass ein int darin gespeichert werden können und a void * können darin gespeichert werden, aber es gibt keinen Hinweis auf Gleichzeitigkeit. NB. Es wäre egal, wenn int und void* hatte eine gemeinsame Anfangssequenz, da diese Regel nur für Strukturen gilt.

    – MM

    28. Januar 2016 um 20:34 Uhr

  • @MM: Ich denke, “beide” implizieren Gleichzeitigkeit auf eine Weise, die “beides” nicht getan hätte, aber wer weiß. Sicherlich sucht das OP angesichts der Rede von Roundtrip-Konvertierungen in der Frage nach Gleichzeitigkeit. Wenn diese Antwort also nicht falsch ist, wird sie zumindest in der falschen Frage gepostet: P

    – Leichtigkeitsrennen im Orbit

    28. Januar 2016 um 22:03 Uhr


1373670cookie-checkVerwendung von intptr_t anstelle von void*?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy