void meint: "nichts".
Wenn Du eine Funktion hast, die als Return void definiert - dann wird diese KEIN Wert zurueckliefern (und sie wird es auch nicht koennen).
Der Compiler prueft, ob Du was erwartest als Return aber die liefert nichts zurueck.
Umgekehrt genauso:
Hast Du eine Funktion, die was zurueck gibt - und wenn nichts definiert wird 'int' angenommen - programmierst ohne was wirklich mit return value; zurueck zu geben - dann wird er meckern.
Es gibt noch zwei andere Bedeutungen von "void":
-
hast Du einen Pointer (mit einer Speicheraddresse als Wert), aber der is unbestimmt, wie denn der Speicher organisiert ist (als bytes, als sequence von 32bit Woertern oder gar Strukturen) - dann sieht man oft (void *). Das ist z.B. bei memcpy() der Fall: das muss nicht wissen, ob der Pointer ausgerichtet ist, auf welche Objekte er zeigt (welcher Typ, es ist typ-invariant).
-
Du kannst auch eine Funktion haben, die als definiert einen Parameter erwartet, z.B.:
void myFunction(int i) {
Aber Du benutzt dann i gar nicht, auch wenn jedesmal beim Aufruf dort ein i uebergeben
wird.
Dann kannst Du in der Funktion schreiben:
(void)i;
Das sagt dem Compiler: auch wenn beim Aufruf ein Wert fuer i erwartet und auch
uebergeben wird: der Wert von i (die Variable i) wird nachfolgend nicht benutzt (ansonsten
ein Warnung des Compilers, dass i nicht verwendet wird.
Vielleicht schon mal das gesehen:
#define NULL (void *)0
Das ist ein ungueltiger Pointer (Speicheraddresse als 0 ist nicht arlaubt, ungueltig). Es ist auch ein "type-invarianter" Pointer:
Wenn nichts bekannt ist, wie der Speicher strukturiert ist (ob Bytes, 32bit-Woerter oder ganze Strukturen dort erwartet und "interpretiert" werden) - dann benutzen wir void.
Bei einem Void-Pointer kannst Du nicht mehr programmieren wie:
i = ptr++;
Der Compiler hat keine Ahnung mit (void *) wie denn die Woerter im Speicher zu behandeln sind: muss ich jetzt ein Byte weiter, 4 Byte fuer 32bit word oder gar N fuer eine Struktur
(void *) hat keine Ahnung und kann den Pointer NICHT auf das naechste Element setzen, da keine Ahnung, wieviel weiter (als Address + N bytes).
So, void hat drei Anwendungen:
-
Eine Funktion gibt nichts zurueck: es kann nichts zugewiesen werden als Return Value, weil nichts zurueck gegeben wird.
-
Ein Parameter, auch wenn erforderlich und gefordert beim Aufruf einer Funktion, wird nicht in Funktion verwendet: (void)i;
-
Ein Pointer hat keine Ahnung wie der Speicher strukturiert ist: (void *)
Der Pointer kann nicht bewegt werden (es sei denn man casted den um in einen anderen Typ).
-
ein NULL Pointer (als (void *)0 ): meint: der Pointer ist nicht initialisiert, er ist ungueltig, er hat keine gueltige Speicheraddress (der Zugriff auf Adresse 0 in allen System ist oft verboten und crasht das System).
So, void meint: "nichts", "nicht gueltig", "nicht verwendet" oder "Type ist nicht bekannt".
Ein ziemlich wichtiges "Feature" um sicher zu programmieren. Daher findet sich dieses void so oft in C/C++ code. Es vermeidet Fehler beim Programnmieren:
wenn mal etwas als void definiert war - dann kann man es auch nicht benutzen.
Oft gilt in C/C++: wenn nicht defiiniert, dann ist es 'int'. Aber das kann fatal sein, z.B. wenn vergessen zu sagen, dass Funktion NICHTS zurueck liefert, aber dafuer 'int' angenommen wird, aber Programmierer vergessen wirklich was zurueck zu geben.
Ich verwende selbst VOID auch bei Funktions-Definition:
Auch wenn es ausreichend ist zu schreiben:
MyFunction() {
ich schreibe immer:
void MyFunction(void) {
Damit wird klar: es wird NICHT das Standard 'int' zurueck gegeben und es werden auch keinerlei Parameter erwartet. Es macht das Programmieren sicherer.