Wie kann ich richtig mit einem void-Zeiger in C?
Kann mir jemand erklären, warum bekomme ich nicht den Wert der variable, aber seine Erinnerung statt?
Brauche ich für nichtig zu verwenden* zeigen Sie auf "unsigned short" Werte.
So wie ich das verstehe void-Zeiger, deren Größe unbekannt ist und deren Typ unbekannt ist.
Einmal initialisieren Sie jedoch, Sie sind dafür bekannt, richtig?
Warum funktioniert meine printf-Anweisung drucken der falsche Wert?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void func(int a, void *res){
res = &a;
printf("res = %d\n", *(int*)res);
int b;
b = * (int *) res;
printf("b =%d\n", b);
}
int main (int argc, char* argv[])
{
//trial 1
int a = 30;
void *res = (int *)a;
func(a, res);
printf("result = %d\n", (int)res);
//trial 2
unsigned short i = 90;
res = &i;
func(i, res);
printf("result = %d\n", (unsigned short)res);
return 0;
}
Die Ausgabe bekomme ich:
res = 30
b =30
result = 30
res = 90
b =90
result = 44974
die printf redest du?
Welche Werte erwarten Sie, und was tun Sie tatsächlich?
Es scheint zu funktionieren hier, Punkt aus, was ungewöhnlich ist und es könnte dir besser helfen.
Ich denke, dass Sie vielleicht ein bisschen wackelig auf den Zeiger. Vielleicht hilft: beej.us/guide/bgc/output/html/multipage/pointers.html
Welche Werte erwarten Sie, und was tun Sie tatsächlich?
Es scheint zu funktionieren hier, Punkt aus, was ungewöhnlich ist und es könnte dir besser helfen.
Ich denke, dass Sie vielleicht ein bisschen wackelig auf den Zeiger. Vielleicht hilft: beej.us/guide/bgc/output/html/multipage/pointers.html
InformationsquelleAutor user900785 | 2011-12-09
Du musst angemeldet sein, um einen Kommentar abzugeben.
Einer Sache, zum im Verstand zu halten: C garantiert nicht, dass
int
werden, die genug Platz für einen Zeiger (einschließlichvoid*
). Das cast ist nicht eine tragbare Sache/gute Idee. Verwenden%p
zuprintf
einen Zeiger.Ebenfalls, Sie machen einen "schlecht gegossen" hier:
void* res = (int*) a
sagt der compiler: "ich bin sicher, dass der Wert vona
ist eine gültigeint*
, so sollten Sie Sie als solche behandeln." Es sei denn, Sie wirklich wissen, für eine Tatsache, dass es eineint
stored at memory address 30, das ist falsch.Glücklicherweise sofort überschreiben
res
mit der Adresse des anderena
. (Sie haben zwei vars namensa
und zwei benannteres
inmain
und diejenigen, die infunc
. Diejenigen, die infunc
sind Kopien der Wert der inmain
, wenn Sie es nennen es.) Allgemein, und überschreiben Sie den Wert eines Parameters an eine Funktion ist "schlecht", aber es ist technisch legal. Persönlich empfehle ich, deklarieren alle Ihre Funktionen " Parameter wieconst
99% der Zeit (z.B.void func (const int a, const void* res)
)Dann, wirkst du
res
zu einemunsigned short
. Ich denke nicht, dass irgendjemand noch auf einen 16-bit Adressraum der CPU (auch ein Apple II vielleicht), so dass definitiv beschädigt den Wert vonres
von abschneiden.In der Regel In C, Typumwandlungen sind gefährlich. Du bist die Aufhebung der compiler die Typ-system, und sagen: "schauen Sie hier, Herr Compiler, ich bin der Programmierer, und ich weiß besser als du, was ich hier habe. Also, Sie nur ruhig sein und machen dies geschehen." Casting von einem Zeiger auf eine nicht-pointer-Typ ist fast durchgängig falsch. Casting zwischen Zeiger-Typen ist eher falsch als nicht.
Ich würde vorschlagen, Check-out einige der "Related" - links unten auf dieser Seite finden Sie einen überblick, wie der C-Typen ein Zeiger arbeiten, im Allgemeinen. Manchmal dauert es zu Lesen über ein paar, um wirklich in den Griff bekommen, wie dieses Zeug geht zusammen.
InformationsquelleAutor BRPocock
ist ein cast auf einen Zeiger, der res ist eine Speicheradresse, die durch Umwandlung einer unsigned short erhalten Sie die Adresse, Wert als unsigned short statt hexadezimal-Wert, um sicher zu sein, dass Sie gehen, um einen korrekten Wert können Sie drucken
Die erste Besetzung
(unsigned short*)res
macht einen cast aufvoid*
Zeiger auf einen Zeiger aufunsigned short
. Sie können dann extrahieren Sie den Wert in die Speicheradresse res verweist durch dereferenzieren es mit der*
InformationsquelleAutor Mansuro
Einen void-Zeiger in C verwendet als eine Art von generischen Zeiger. Ein void-Zeiger-variable kann verwendet werden, um enthalten die Adresse einer variable Typ. Das problem mit einem void-Zeiger nach der Zuweisung einer Adresse an den Zeiger, der Informationen über den Typ der variable ist nicht mehr verfügbar für den compiler zu überprüfen.
Im Allgemeinen, void-Zeiger sollte vermieden werden, da sich der Typ der Variablen, deren Adresse in der void-Zeiger ist nicht mehr verfügbar, die für den compiler. Auf der anderen Seite gibt es Fälle, wo ein void-Zeiger ist sehr praktisch. Allerdings ist es für den Programmierer wissen, die Art der variable, deren Adresse in der void-Zeiger-variable, und um es richtig zu nutzen.
Viel von älteren C-Quelle C-Stil-casts zwischen Typ Zeiger und void-Zeiger. Dies ist nicht notwendig mit modernen Compilern und sollte vermieden werden.
In der Größe eines void-Zeiger-variable bekannt ist. Was nicht bekannt ist, ist die Größe der variable, deren Zeiger der void-Zeiger variable. Zum Beispiel hier sind einige Quellcode-Beispiele.
Einer Weise, die void-Zeiger verwendet wurden, ist durch verschiedene Arten von Strukturen, die als argument für eine Funktion, in der Regel irgendeine Art von dispatching-Funktion. Da die Schnittstelle für die Funktion können für verschiedene pointer-Typen, einen void-Zeiger verwendet werden muss, der in der argument Liste. Dann ist der Typ der Variablen hingewiesen wird bestimmt, indem entweder ein zusätzliches argument oder Inspektion der Variablen hingewiesen. Ein Beispiel dieser Art der Verwendung einer Funktion wäre, etwas wie das folgende. In diesem Fall schließen wir eine Anzeige, die den Typ der struct in das erste Mitglied der verschiedenen Permutationen der struct. Solange alle Strukturen, die verwendet werden, mit dieser Funktion als erstes Mitglied einer
int
Angabe der Art der Struktur, das funktionieren wird.Etwas wie die oben genannten hat eine Reihe von software-design-Probleme mit der Kopplung und Kohäsion, so dass es sei denn, Sie haben gute Gründe für die Verwendung dieses Ansatzes ist es besser, neu zu überdenken, Ihr Entwurf. Aber die C-Programmiersprache ermöglicht es Ihnen, dies zu tun.
Es gibt einige Fälle, wo die void-Zeiger erforderlich ist. Zum Beispiel die
malloc()
Funktion, die Speicher zuweist, liefert einen void-Zeiger enthält die Adresse des Bereichs, der reserviert wurde (oder NULL, wenn die Zuordnung fehlgeschlagen ist). Der void-Zeiger in diesem Fall können für eine einzelnemalloc()
Funktion zurückgeben kann die Adresse des Speichers, der für jede Art von variable. Das folgende zeigt die Verwendung vonmalloc()
mit verschiedenen Variablen-Typen.InformationsquelleAutor Richard Chambers
Wenn das, was Sie tun möchten, übergeben Sie die variable
a
von Namen und verwenden Sie es, probieren Sie etwas wie:Wenn Sie eine
void*
aus einer library-Funktion, und Sie wissen, Ihre eigentliche Art, sollten Sie sofort speichern Sie es in eine variable des richtigen Typs:Gibt es ein paar Situationen, in denen Sie zu erhalten, einen parameter per Referenz als eine
void*
und dann warf er. Die, die ich habe, laufen Sie in den meisten Fällen in der realen Welt ist eine thread-Prozedur. So, könnten Sie etwas schreiben wie:Wenn Sie wollen, gefährlich zu Leben, die Sie nicht passieren konnten, ein
uintptr_t
Wert umgewandeltvoid*
und warf es wieder, aber Vorsicht trap-Repräsentationen.InformationsquelleAutor Davislor
printf("result = %d\n", (int)res);
ist der Druck den Wert von res (pointer) als eine Nummer.Denken Sie daran, dass ein pointer ist eine Adresse im Speicher, so dass diese gedruckt wird einige random suchen 32bit Zahl.
Wenn Sie etwas drucken wollte, der gespeicherte Wert an der angegebenen Adresse, dann müssen Sie (int)*res - obwohl das (int) ist unnötig.
edit: wenn Sie möchten, drucken Sie den Wert (ie -) der Zeiger dann sollten Sie
%p
es ist im wesentlichen die gleiche, aber die Formate die es besser versteht und wenn die Größe eines int und eines poitner sind verschiedene über Ihre PlattformInformationsquelleAutor Martin Beckett
Wenn Sie einen void-Zeiger
ptr
dass Sie wissen, verweist auf eineint
, um Zugang zu, dassint
schreiben:Erste warf es auf einen Zeiger auf int mit cast-operator
(int*)
und dann dereferenzieren, um die Spitzen-Wert.Sind Sie Gießen Sie den Zeiger direkt auf einen Wert geben, und obwohl der compiler glücklich machen, das ist wohl nicht das, was Sie wollen.
InformationsquelleAutor rodrigo
a ist ein int aber kein ptr, vielleicht sollte es sein:
nicht ganz Ihre Frage zu verstehen. Grundsätzlich werden die void* - pointer kann zeigen Sie auf alle Arten. brauchen nicht explizite Typ-Umwandlung.
InformationsquelleAutor zchenah
In der Größe eines void-Zeiger ist bekannt; es ist von der Größe eine Adresse, also die gleiche Größe wie alle anderen Zeiger. Sie sind frei konvertieren zwischen einem integer und einen Zeiger, und das ist gefährlich. Wenn du meinst, nehmen Sie die Adresse der Variablen
a
Sie brauchen, um zu konvertieren seine Adresse auf einevoid *
mit(void *)&a
.InformationsquelleAutor mkb