2016-03-28 8 views
3

Ist eine uintmax_t Garantie groß genug, um einen Funktionszeiger zu halten?kann (u) intmax_t einen Funktionszeiger halten?

i wissen:

folgenden Typs bezeichnet eine ganze Zahl ohne Vorzeichen Typ fähig beliebigen Wert jeder unsigned integer Typ darstellt:

uintmax_t 

und

Der folgende Typ bezeichnet einen Ganzzahltyp ohne Vorzeichen mit Eigenschaft, die jeder gültiger Zeiger auf void kann auf diese Art umgewandelt werden, umgewandelt dann wieder auf einen Zeiger auf void, und das Ergebnis wird gleich den ursprünglichen Zeiger vergleichen: uintptr_t

und dass ein hohlraum Pointer ist möglicherweise nicht groß genug, um einen Funktionszeiger zu halten, so dass ein uintptr_t auch nicht groß genug ist, um einen Funktionszeiger zu halten.

+0

würde ich denken, es würde groß genug sein, aber ich kann nicht Dokumentation unterstützen. Diese Frage könnte relevant sein: http://stackoverflow.com/questions/15823217/does-the-c-standard-guarantee-that-stduintmax-t-can-hold-all-values-of-std –

+1

Wenn der Standard doesn Sag es nicht, dann denke ich, die Antwort ist nein. (AFAIK, der Standard erlaubt keine Konvertierung/Verrücktheit mit Funktionszeigern.) –

+0

Konvertierung eines Funktionszeigers zu einer Ganzzahl oder einem Objektzeiger ist undefiniertes Verhalten. Dies beinhaltet "void *". – Olaf

Antwort

4

Nein, nicht im Allgemeinen. void* und in der Folge [u]intptr_t sind nur garantiert breit genug, um Objektzeiger zu halten, das sind Zeiger auf Objekttypen. Funktionszeiger können auf einigen Plattformen breiter sein und mehr Informationen als nur einen Eintrittspunkt zu der Funktion umfassen. Auf solchen Plattformen hat ein void* oder uintptr_t nicht genug Bits, um alle Informationen darzustellen, die benötigt würden.

Auf vielen Plattformen haben Funktionszeiger die gleiche Breite wie Objektzeiger und können sogar die Konvertierung von einem zum anderen ermöglichen. Dies ist jedoch eine Erweiterung des C-Standards und Sie müssten dies mit Ihrer Plattform-Dokumentation überprüfen.

4

Eine solche Garantie gibt es in der C-Norm nicht.

Erstens gibt es keine Garantie dafür, dass ein Pointer verlustfrei in einen Integer-Typ umgewandelt werden kann (mit Ausnahme eines NULL-Pointers). Es ist wahr, dassniconin der Lage sein muss, einen leeren Zeiger (und somit irgendeinen Objektzeiger) verlustfrei darzustellen. Es gibt jedoch keine Garantie, dass eine Implementierung uintptr_t hat, da sie und intptr_t optional sind (letzter Satz von § 7.20.1.4).

Zweitens ist ein Funktionszeiger kein Objektzeiger, und es ist nicht unbedingt möglich, einen in einen void-Zeiger und zurück zu konvertieren. Selbst wenn.existiert, ist es möglicherweise nicht groß genug, um einen Funktionszeiger zu halten.

Auf einer mit X/Open System Interface (XSI) kompatiblen Implementierung (die meisten Posix-Systeme) müssen Sie in der Lage sein, zwischen void-Zeigern und Funktionszeigern zu konvertieren, und uintptr_t muss existieren. In diesem Fall haben Sie die Garantie. (Die Konvertibilität zwischen Hohlraum und Funktionszeigern benötigt wird von der dlsym Systemschnittstelle, die von XSI bewegt wurde Posix in Heft 7 (2008) zu stützen. Allerdings setzt die Existenz von uintptr_t eine XSI Erweiterung sein.)

1

Ist eine uintmax_t-Garantie groß genug, um einen Funktionszeiger zu halten?

Kein garantierter Weg als auch von anderen beantwortet.


Noch die Größe eines Funktionszeigers existiert und es hat ein Bitmuster. Wenn ausreichend groß, könnte uintmax_t das Bitmuster des Zeigers halten (und vielleicht mehr). Dieser Größentest könnte zur Kompilierzeit bewertet werden.

#include <assert.h> 
#include <stdio.h> 
#include <stdint.h> 

int foo(int x) { 
return x+x; 
} 

int main(void) { 
    union { 
    uintmax_t um; 
    int (*fp)(int); 
    } u = {0}; 
    assert(sizeof u.um >= sizeof u.fp); // This assertion may fail 
    u.fp = foo; 

    uintmax_t save = u.um; 
    printf("%ju\n", save); 

    u.um = save; 
    printf("%d\n", (*u.fp)(42)); 

    return 0; 
} 

Ausgabe

4198816 
84 
Verwandte Themen