2009-01-04 11 views
11

Ich lese einige Code in der Ogre3D Implementierung und ich kann nicht verstehen, was eine void * Typ Variable bedeutet. Was bedeutet ein Zeiger auf void in C++?Zeiger auf void in C++?

Antwort

39

Ein Zeiger auf void, void* kann auf jedes Objekt zeigen:

int a = 5; 
void *p = &a; 

double b = 3.14; 
p = &b; 

Sie können nicht dereferenzieren, Zunahme oder -abnahme, die Zeiger, weil Sie nicht wissen, welche Art Sie zu zeigen. Die Idee ist, dass void* für Funktionen wie memcpy verwendet werden kann, die nur Speicherblöcke kopieren und sich nicht um den Typ kümmern, den sie kopieren.

+0

waw - Ich wusste nicht, dass Sie eine Lücke nicht erhöhen konnten *! Vielen Dank! – xtofl

+0

Einige Compiler lassen Sie - sie nehmen an, dass alle Zeigertypen 32bit sind. Das ist falsch, aber unter Windows üblich, wo Leute von einem 32bit x86 ausgehen. –

+0

@mgb: Nie einen solchen Compiler gesehen. – dalle

4

Es ist nur ein allgemeiner Zeiger, verwendet, um Daten zu übergeben, wenn Sie den Typ nicht kennen. Sie müssen es in den richtigen Typ umwandeln, um es zu verwenden.

2

Es ist ein Zeiger auf alles - nur ein Stück Speicher, mit dem Sie spielen können - könnte ein Objekt sein, könnte ein Char sein. Sie müssen etwas tun, um damit etwas Nützliches zu tun.

2

Building off my prior posting...


ACHTUNG: Alle hier Speicheradressen fiktiv sind. Ich mache sie nur um einen Punkt zu verdeutlichen.


Gegeben:

int data[] = {10,11,12}; 

Wir haben jetzt:

0xffff0000-0xffff0003 with a value of (int)(10) 
0xffff0004-0xffff0007 with a value of (int)(11) 
0xffff0008-0xffff000b with a value of (int)(12) 

(Ich bin nicht in Big-Endian-vs Little-Endian Byte-Reihenfolge zu uns kommen würde.)

Wenn wir haben:

int * p = data; 

Wir haben jetzt einen anderen Speicherort woanders haben, sagen:

0xaaaa0000-0xaaaa0003 with a value of (int*)0xffff0000 

Wir p verwenden können [1] [oder * (p + 1)] beziehen sich auf * (int *) (0xffff0004) [= 11] als sizeof (int) = 4 und 0xffff0000 + sizeof (int) = 0xffff0004.

Wenn wir:

void * v = data; 

Wir haben jetzt einen anderen Speicherort woanders, sagen:

0xbbbb0000-0xbbbb0003 with a value of (void*)0xffff0000. 

jedoch ungültig nicht mit einem sizeof() Informationen haben.Wir können den Zeiger nicht erhöhen oder verringern. Wir können den Zugriff auf die in 0xffff0000 gespeicherten Daten nicht dereferenzieren. Wir können den Wert nur als rohe Speicheradresse verwenden.

Wenn wir die in (void *) 0xffff0000 gespeicherten Daten verwenden möchten, müssen wir sie zunächst auf einen geeigneten Typ umwandeln.

Das heißt, (void *) ist immer noch sehr nützlich als Mittel zur Weitergabe von Adressen an beliebige Datenstrukturen herum. Zum Beispiel, memset(). Es spielt keine Rolle, ob ich ein struct tm oder ein struct sockaddr zero'ing. Wir brauchen nur einen Zeiger auf die Struktur und ihre Größe.

(Diese Selbstverständlichkeit sollte, aber ... Vorsicht Memset mit einer Klasseninstanz auf Null und, dabei, die virtuelle Zeigertabelle zu überschreiben.)

1

Ein void-Zeiger kann nicht auf ein Klassenmitglied Punkt in C++.

+0

Das stimmt, sie sind unterschiedlich große Zeiger. – Joshua

+0

Ich denke, das ist, weil Member-Zeiger völlig anders strukturiert sind. Wenn Sie wollen, dann können Sie sagen, dass sie in einem anderen Adressraum leben (und dann ist der Grund derselbe wie der Grund, warum Sie nicht auf eine Funktion verweisen können, die 'void *' verwendet). Für Größen hat ein Datenelementzeiger auf GCC (nach dem Itanium ABI) die Größe eines 'ptrdiff_t' - es entspricht der Größe eines' int * 'auf meinem PC - der Adressraum ist der Offset vom Anfang des Objekt auf seinen letzten Mitglied Offset. Für Verweise auf Member-Funktionen ist die Größe natürlich auch größer, aber natürlich auch. –