Frage

Ich habe eine Funktion, deren gesehenen Prototyp ist:

int myfunc(void** ppt)

Mit dieser Funktion in einer C-Datei aufgerufen wird als     a = myfunc (mystruct ** var1);

wo mystruct ist typedef für eine der Struktur, die wir haben.

Dies funktioniert ohne Kompilierungsfehlern in MSVC6.0, aber wenn ich es mit einem anderen C-Compiler zu kompilieren, gibt es einen Fehler an der Stelle, wo diese Funktion mit Fehlermeldung genannt wird:

Argumente vom Typ mystruct ** sind nicht kompatibel mit dem Parameter vom Typ void **

Das Argument von myfunc () als nichtig gehalten ** weil es scheint, eine generische malloc Art von Funktion, um mit verschiedener Struktur-Variablen-Typ für Speicherzuweisung aufgerufen werden

  1. Gibt es eine Art, wie nichtig ** in C-Standard erlaubt / alle C-Compiler?
  2. Wie kann ich dieses Problem beheben? [Ich habe versucht, die Funktionsaufruf Argument Gießens mystruct**, aber es hat nicht funktioniert]

-AD

War es hilfreich?

Lösung

void** ist gültig, aber abhängig von Ihrer Fehlermeldung, haben Sie wahrscheinlich ausdrücklich das Argument werfen wie folgt:

mystruct **var1;
x = myfunc ((void**) var1);

Das ist, weil die myfunc Funktion des void** Typ erwartet. Während void* implizit in jeden anderen Zeiger gegossen werden, das ist nicht so für den Doppelzeiger -. Sie müssen es explizit werfen

Andere Tipps

Die comp.lang.c FAQ Adressen dieses Problem im Detail in Frage 4.9 . Kurz gesagt, sagen sie es ist nicht unbedingt tragbar einen beliebigen Zeiger auf Zeiger auf einen void ** zu werfen; sie gehen auf zu erklären, dass „Code wie dies funktionieren kann und manchmal empfohlen wird, aber es stützt sich auf alle Zeigertypen die gleiche interne Darstellung mit (was üblich ist, aber nicht universal).“ Sie gehen auf zu erklären, dass „jeder void ** Wert, den Sie mit spielen die Adresse eines tatsächlichen void * Wert irgendwo sein muss, wirft wie (void **)&dp, obwohl sie den Compiler up schließen können, sind nonportable (und vielleicht nicht einmal das tun, was Sie wollen).“

So können Sie sicher / portably das gewünschte Verhalten mit Code erreichen, wie:

some_type *var1 = foo();
void *tmp_void_ptr = (void *)var1;
myfunc(&tmp_void_ptr);

Es gibt einen Grund der Compiler nicht automatisch aus mystruct** werfen kann void**.

Betrachten Sie den folgenden Code ein:

void stupid(struct mystruct **a, struct myotherstruct **b)
{
    void **x = (void **)a;
    *x = *b;
}

Der Compiler wird nicht über die implizite Umwandlung von myotherstruct* klagt in der void* Linie *x = *b, obwohl diese Linie einen Zeiger auf eine myotherstruct an einem Ort zu setzen versucht, wo nur Zeiger sollten auf mystruct gesetzt werden.

Der Fehler ist in der Tat in der vorhergehenden Zeile, die „einen Zeiger auf einen Ort, an den Zeiger kann mystruct wird gesetzt“ wird die Umstellung auf „ein Zeiger auf einen Ort, an den Zeiger auf alles kann sein stellen". Diese ist der Grund, gibt es keine implizite Umwandlung ist. Natürlich, wenn Sie eine explizite Umwandlung verwenden, der Compiler vorausgesetzt, dass Sie wissen, was Sie tun.

Diese Frage ist etwas verwirrend. Aber ja, void ** ist sicherlich rechtliche und gültig C, und bedeutet „Zeiger auf Zeiger auf void“ wie erwartet.

Ich bin über Ihr Beispiel eines Anrufs nicht sicher, ob die Argumente ( „mystruct ** var1“) macht keinen Sinn. Wenn var1 vom Typ mystruct ** ist, sollte der Anruf nur a = func(var1); lesen, könnte dies ein Tippfehler sein.

Casting sollte funktionieren, aber Sie müssen void ** werfen, denn das ist es, was die Funktion erwartet.

Wie schmutzig, wie es aussehen kann. Manchmal kann man nicht ein Problem, ohne Leere ** lösen

Ja, void ** ist durchaus akzeptabel und sehr nützlich unter bestimmten Umständen. Beachten Sie auch, dass die Erklärung void **foo und void *bar gegeben, wird der Compiler weiß, dass die Größe des Objekts, auf die foo (es auf einen Zeiger verweist, und alle Zeiger die gleiche Größe haben, außer auf einigen alten Plattformen, die Sie brauchen nicht zu kümmern) , aber es wird die Größe des Objekts nicht wissen, von Bar zeigte (es auf ein Objekt jeder Größe zeigen könnte). Sie können also sicher Zeigerarithmetik auf void ** Zeiger aber nicht auf void * Zeiger ausführen. Sie müssen sie auf etwas werfen anderes zuerst, wie ein char *. GCC ermöglicht es Ihnen, dass void * und char * äquivalent sind, so zu tun, die jeweils auf ein Objekt zeigt ein einzelnes Byte in Größe, aber das ist nicht dem Standard entsprechende und nonportable.

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