Ist es möglich, einen ungültigen Zeiger ohne Typumwandlung in der Programmiersprache C zu dereferenzieren?
Gibt es auch eine Möglichkeit, eine Funktion zu verallgemeinern, die einen Zeiger empfangen und in einem ungültigen Zeiger speichern kann, und können wir mithilfe dieses ungültigen Zeigers eine verallgemeinerte Funktion erstellen?
für zB:
void abc(void *a, int b)
{
if(b==1)
printf("%d",*(int*)a); // If integer pointer is received
else if(b==2)
printf("%c",*(char*)a); // If character pointer is received
else if(b==3)
printf("%f",*(float*)a); // If float pointer is received
}
Ich möchte diese Funktion generisch machen, ohne if-else-Anweisungen zu verwenden. Ist dies möglich?
Auch wenn es gute Internetartikel gibt, die das Konzept eines ungültigen Zeigers erklären, wäre es vorteilhaft, wenn Sie die URLs angeben könnten.
Ist auch eine Zeigerarithmetik mit leeren Zeigern möglich?
quelle
void *
Zeiger genauso wiechar *
, aber es ist kein Standard und Sie sollten sich nicht darauf verlassen.In C
void *
kann a ohne explizite Umwandlung in einen Zeiger auf ein Objekt eines anderen Typs konvertiert werden:Dies hilft jedoch nicht dabei, Ihre Funktion allgemeiner zu schreiben.
Sie können a nicht dereferenzieren,
void *
wenn Sie es in einen anderen Zeigertyp konvertieren, da das Dereferenzieren eines Zeigers den Wert des Objekts erhält, auf das gezeigt wird. Ein nacktervoid
Typ ist kein gültiger Typ, daher ist eine Dereferenzierungvoid *
nicht möglich.Bei der Zeigerarithmetik geht es darum, Zeigerwerte um ein Vielfaches der
sizeof
Objekte zu ändern, auf die verwiesen wird. Da diesvoid
kein wahrer Typ ist,sizeof(void)
hat er keine Bedeutung, sodass die Zeigerarithmetik für nicht gültig istvoid *
. (Einige Implementierungen erlauben dies unter Verwendung der entsprechenden Zeigerarithmetik fürchar *
.)quelle
void abc(void *a, int b)
. Aber warum nicht verwendenvoid abc(int *a, int b)
, da in Ihrer Funktion, die Sie schließlich definieren werdenint *test = a;
, eine Variable gespeichert wird, und ich sehe keine weiteren Vorteile, wenn Sie eine andere Variable definieren. Ich sehe viele Codes, die auf diese Weisevoid *
als Parameter geschrieben wurden und später in der Funktion Variablen umwandeln . Da diese Funktion jedoch vom Autor geschrieben wurde, muss er die Verwendung der Variablen kennen. Warum alsovoid *
? Vielen DankSie sollten sich bewusst sein, dass es in C im Gegensatz zu Java oder C # absolut keine Möglichkeit gibt, den Objekttyp, auf den ein
void*
Zeiger zeigt , erfolgreich zu "erraten" . Ähnliches gibt esgetClass()
einfach nicht, da diese Informationen nirgends zu finden sind. Aus diesem Grund enthält die Art von "generisch", nach der Sie suchen, immer explizite Metainformationen, wie dieint b
in Ihrem Beispiel oder die Formatzeichenfolge in derprintf
Funktionsfamilie.quelle
Ein ungültiger Zeiger wird als generischer Zeiger bezeichnet, der auf Variablen eines beliebigen Datentyps verweisen kann.
quelle
Bisher verstehe ich den leeren Zeiger wie folgt.
Wenn eine Zeigervariable mit dem Schlüsselwort void deklariert wird, wird sie zu einer universellen Zeigervariable. Die Adresse einer Variablen eines beliebigen Datentyps (char, int, float usw.) kann einer ungültigen Zeigervariable zugewiesen werden.
Da ein anderer Datentypzeiger dem ungültigen Zeiger zugewiesen werden kann, habe ich ihn in der Funktion absolut_value (Code unten gezeigt) verwendet. Um eine allgemeine Funktion zu machen.
Ich habe versucht, einen einfachen C-Code zu schreiben, der Integer oder Float als Argument verwendet und versucht, ihn + ve zu machen, wenn er negativ ist. Ich habe den folgenden Code geschrieben:
Aber ich habe einen Fehler bekommen, also habe ich erfahren, dass mein Verständnis mit dem leeren Zeiger nicht korrekt ist :(. Also werde ich jetzt darauf zugehen, Punkte zu sammeln, warum ist das so?
Die Dinge, die ich mehr über leere Zeiger verstehen muss, sind die folgenden.
Wir müssen die Void-Zeigervariable typisieren, um sie zu dereferenzieren. Dies liegt daran, dass einem ungültigen Zeiger kein Datentyp zugeordnet ist. Der Compiler kann auf keinen Fall wissen (oder raten?), Auf welche Art von Daten der Void-Zeiger zeigt. Um die Daten zu erfassen, auf die ein ungültiger Zeiger zeigt, geben wir sie mit dem richtigen Typ der Daten ein, die sich in der Position der ungültigen Zeiger befinden.
Ein ungültiger Zeiger kann sehr nützlich sein, wenn der Programmierer nicht sicher ist, welchen Datentyp die vom Endbenutzer eingegebenen Daten haben. In einem solchen Fall kann der Programmierer einen leeren Zeiger verwenden, um auf die Position des unbekannten Datentyps zu zeigen. Das Programm kann so eingestellt werden, dass der Benutzer aufgefordert wird, die Art der Daten zu informieren, und das Typ-Casting kann gemäß den vom Benutzer eingegebenen Informationen durchgeführt werden. Ein Code-Snippet ist unten angegeben.
Ein weiterer wichtiger Punkt, den Sie bei leeren Zeigern beachten sollten, ist, dass - Zeigerarithmetik nicht in einem leeren Zeiger ausgeführt werden kann.
Jetzt verstand ich, was mein Fehler war. Ich korrigiere das gleiche.
Verweise :
http://www.antoarts.com/void-pointers-in-c/
http://www.circuitstoday.com/void-pointers-in-c .
Der neue Code ist wie unten gezeigt.
Danke dir,
quelle
Nein, das ist nicht möglich. Welchen Typ sollte der dereferenzierte Wert haben?
quelle
quelle
printf
. Diese Antwort hat ein gutes Beispiel dafür.int b
eine Aufzählung ersetzen , aber eine spätere Änderung dieser Aufzählung würde diese Funktion beeinträchtigen.Der einzige einfache Weg, den ich sehe, ist die Verwendung von Überladung. Dies ist in der C-Programmiersprache AFAIK nicht verfügbar.
Haben Sie die C ++ - Programmiersprache für Ihr Programm berücksichtigt? Oder gibt es eine Einschränkung, die die Verwendung verbietet?
quelle
Hier ist ein kurzer Hinweis auf
void
Zeiger: https://www.learncpp.com/cpp-tutorial/613-void-pointers/Angenommen, der Arbeitsspeicher der Maschine ist byteadressierbar und erfordert keine ausgerichteten Zugriffe. Die allgemeinste und atomarste (der Darstellung auf Maschinenebene am nächsten liegende) Art, a zu interpretieren,
void*
ist ein Zeiger auf ein Byteuint8_t*
. Wenn Sie avoid*
in auint8_t*
umwandeln, können Sie beispielsweise die ersten 1/2/4/8 / beliebig vielen Bytes ausdrucken, die an dieser Adresse beginnen, aber Sie können nicht viel anderes tun.quelle
Sie können problemlos einen leeren Drucker drucken
quelle
void
die gleiche Größe hat wieint
?void
Zeigers, sondern das Druckenint
an der Speicheradresse, die der Zeiger enthält (was in diesem Fall der Wert von wärep
).Da C eine statisch typisierte, stark typisierte Sprache ist, müssen Sie vor dem Kompilieren den Variablentyp festlegen. Wenn Sie versuchen, Generika in C zu emulieren, werden Sie am Ende versuchen, C ++ erneut zu schreiben. Daher ist es besser, stattdessen C ++ zu verwenden.
quelle
Der Void-Zeiger ist ein generischer Zeiger. Die Adresse eines beliebigen Datentyps einer Variablen kann einem Void-Zeiger zugewiesen werden.
quelle
Sie können einen Zeiger nicht dereferenzieren, ohne seinen Typ anzugeben, da verschiedene Datentypen unterschiedliche Speichergrößen haben, dh ein int ist 4 Byte, ein Zeichen ist 1 Byte.
quelle
Grundsätzlich sind in C "Typen" eine Möglichkeit, Bytes im Speicher zu interpretieren. Zum Beispiel was der folgende Code
Sagt "Wenn ich main ausführe, möchte ich 4 (Größe der Ganzzahl) + 4 (Größe der Ganzzahl) = 8 (Gesamtbytes) Speicher zuweisen. Wenn ich '.x' als l-Wert auf einen Wert mit der Typbezeichnung schreibe Zeigen Sie zur Kompilierungszeit, rufen Sie Daten aus dem Speicherort des Zeigers plus vier Bytes ab. Geben Sie dem Rückgabewert die Bezeichnung zur Kompilierungszeit "int". "
Zur Laufzeit im Computer sieht Ihre "Punkt" -Struktur folgendermaßen aus:
Und so
void*
könnte Ihr Datentyp aussehen: (unter der Annahme eines 32-Bit-Computers)quelle
Dies wird nicht funktionieren, aber void * kann viel dazu beitragen, einen generischen Zeiger auf Funktionen zu definieren und ihn als Argument an eine andere Funktion zu übergeben (ähnlich wie beim Rückruf in Java) oder eine Struktur zu definieren, die oop ähnelt.
quelle