Heim  >  Artikel  >  php教程  >  Verstehen Sie die Bedeutung von Void und Void-Zeigern genau

Verstehen Sie die Bedeutung von Void und Void-Zeigern genau

高洛峰
高洛峰Original
2016-12-13 13:15:531499Durchsuche

Die Bedeutung von void
void ist „typlos“, void * ist „typloser Zeiger“, der auf jeden Datentyp verweisen kann.

Verwendungsspezifikationen für Void-Zeiger
①Der Void-Zeiger kann auf jeden Datentyp zeigen, das heißt, ein Zeiger eines beliebigen Datentyps kann verwendet werden, um dem Void-Zeiger einen Wert zuzuweisen. Zum Beispiel:
int *pint;
void *pvoid; Sie müssen die Typkonvertierung erzwingen, z. B.: pint = (int *)pvoid;

② Im ANSI-C-Standard sind arithmetische Operationen wie pvoid++ oder pvoid+=1 usw. nicht zulässig void-Zeiger, aber in GNU ist es erlaubt, da GNU standardmäßig void * als dasselbe wie char * betrachtet. sizeof( *pvoid )== sizeof( char ).


Die Rolle von void

①Einschränkungen bei der Funktionsrückgabe.

②Einschränkungen bei Funktionsparametern.
Wenn eine Funktion keinen Wert zurückgeben muss, muss die Void-Qualifikation verwendet werden. Zum Beispiel: void func(int, int);
Wenn eine Funktion keine Parameter akzeptieren darf, muss die Void-Qualifikation verwendet werden. Zum Beispiel: int func(void).

Da der Void-Zeiger auf jeden Datentyp zeigen kann, kann ein Zeiger eines beliebigen Datentyps verwendet werden, um dem Void-Zeiger einen Wert zuzuweisen, sodass auch der Void-Zeiger verwendet werden kann als Funktionsparameter, sodass die Funktion jeden Zeiger auf einen Datentyp als Parameter akzeptieren kann. Zum Beispiel:

void * memcpy( void *dest, const void *src, size_t len ​​​​);
void * memset( void * buffer, int c, size_t num );

Viele Anfänger sind verwirrt über die Zeigertypen void und void in der C/C++-Sprache, die nicht gut verstanden werden, daher gibt es einige Fehler bei der Verwendung. In diesem Artikel wird die tiefgreifende Bedeutung des Schlüsselworts void erläutert. Im Folgenden werden die Verwendungsmethoden und -techniken von void und den Zeigertypen void erläutert.

1. Regeln für die vorsichtige Verwendung von Void-Zeigertypen

Gemäß dem ANSI-Standard (American National Standards Institute) können arithmetische Operationen nicht auf Void-Zeigern ausgeführt werden, d. h. die folgenden Operationen sind illegal:

void*pvoid;
pvoid++;//ANSI: Error
pvoid+=1;//ANSI: Error
//Der Grund, warum der ANSI-Standard dies erkennt, liegt darin, dass er darauf besteht, dass der Zeiger für algorithmisch ist Operationen müssen sicherstellen, dass der Datentyp bekannt ist, auf den sie verweisen.
//Zum Beispiel:
int*pint;
pint++;//ANSI: Richtig
Das Ergebnis von pint++ ist eine Vergrößerung von sizeof(int).
Aber das berühmte GNU (Abkürzung für GNU'sNotUnix) glaubt das nicht. Es legt fest, dass die Algorithmusoperation von void* mit char* übereinstimmt.
Die folgenden Anweisungen sind also im GNU-Compiler korrekt:
pvoid++; //GNU: korrekt
pvoid+=1; //GNU: korrekt
Das Ausführungsergebnis von pvoid++ ist, dass es um 1 erhöht wird .
Um den ANSI-Standard zu erfüllen und die Portabilität des Programms zu verbessern, können wir in der tatsächlichen Programmierung Code schreiben, um die gleiche Funktion wie folgt zu erreichen:
void*pvoid;
(char*)pvoid++; / /ANSI: richtig; GNU: richtig
(char*)pvoid+=1;//ANSI: falsch; GNU: richtig
Es gibt einige Unterschiede zwischen GNU und ANSI. als ANSI und bietet Unterstützung für mehr Syntaxen. Aber wenn wir im wirklichen Leben entwerfen, sollten wir uns dennoch so weit wie möglich an die ANSI-Standards halten.

2. Wenn der Parameter einer Funktion ein Zeiger eines beliebigen Typs sein kann, sollte sein Parameter als void* deklariert werden

Typische Funktionsprototypen wie Speicheroperationsfunktionen memcpy und memset :

void *memcpy(void*dest,constvoid*src,size_tlen);
void*memset(void*buffer,intc,size_tnum);
Auf diese Weise kann jede Art von Zeiger übergeben werden Memcpy und Memset verkörpern wirklich die Bedeutung der Speicheroperationsfunktion, da das von ihr betriebene Objekt nur ein Teil des Speichers ist, unabhängig davon, um welche Art von Speicher es sich handelt. Es wäre wirklich seltsam, wenn der Parametertyp von memcpy und memset nicht void*, sondern char* wäre! Solche Memcpy- und Memset-Funktionen sind offensichtlich keine „reinen, spaßfreien“ Funktionen!
Der folgende Code wird korrekt ausgeführt:
//Beispiel: memset akzeptiert Zeiger jeden Typs
int intarray[100];
memset(intarray,0,100*sizeof(int));//Intarray löschen 0
//Beispiel: memcpy akzeptiert jede Art von Zeiger
int intarray1[100], intarray2[100];
memcpy(intarray1,intarray2,100*sizeof(int));//Kopiere intarray2 nach intarray1
Interessant ist, dass die Funktionen memcpy und memset auch den Typ void* zurückgeben. Wie kompetent die Autoren der Standardbibliotheksfunktionen sind!

3. Regel 3: void kann keine reale Variable darstellen

Die folgenden Codes versuchen alle, void eine reale Variable darzustellen, daher sind sie alle falsche Codes:

voida; // Fehler
function(voida);//Error
void verkörpert eine Abstraktion. Variablen in dieser Welt sind alle „typisiert“. Beispielsweise ist eine Person entweder ein Mann oder eine Frau (und eine Transe?).
Das Erscheinungsbild von void dient nur einem abstrakten Bedarf. Wenn Sie das Konzept der „abstrakten Basisklasse“ im objektorientierten Bereich richtig verstehen, ist der Datentyp void leicht zu verstehen. So wie wir keine Instanz einer abstrakten Basisklasse definieren können, können wir auch keine void-Variable (nennen wir void analog einen „abstrakten Datentyp“) definieren.

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn