Galileo Computing < openbook > Galileo Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.

Inhaltsverzeichnis
Vorwort
Vorwort des Gutachters
1 Einstieg in C
2 Das erste Programm
3 Grundlagen
4 Formatierte Ein-/Ausgabe mit »scanf()« und »printf()«
5 Basisdatentypen
6 Operatoren
7 Typumwandlung
8 Kontrollstrukturen
9 Funktionen
10 Präprozessor-Direktiven
11 Arrays
12 Zeiger (Pointer)
13 Kommandozeilenargumente
14 Dynamische Speicherverwaltung
15 Strukturen
16 Ein-/Ausgabe-Funktionen
17 Attribute von Dateien und das Arbeiten mit Verzeichnissen (nicht ANSI C)
18 Arbeiten mit variabel langen Argumentlisten – <stdarg.h>
19 Zeitroutinen
20 Weitere Headerdateien und ihre Funktionen (ANSI C)
21 Dynamische Datenstrukturen
22 Algorithmen
23 CGI mit C
24 MySQL und C
25 Netzwerkprogrammierung und Cross–Plattform-Entwicklung
26 Paralleles Rechnen
27 Sicheres Programmieren
28 Wie geht’s jetzt weiter?
A Operatoren
B Die C-Standard-Bibliothek
Stichwort

Download:
- ZIP, ca. 10,6 MB
Buch bestellen
Ihre Meinung?

Spacer
<< zurück
C von A bis Z von Jürgen Wolf
Das umfassende Handbuch
Buch: C von A bis Z

C von A bis Z
3., aktualisierte und erweiterte Auflage, geb., mit CD und Referenzkarte
1.190 S., 39,90 Euro
Galileo Computing
ISBN 978-3-8362-1411-7
Pfeil 12 Zeiger (Pointer)
Pfeil 12.1 Zeiger deklarieren
Pfeil 12.2 Zeiger initialisieren
Pfeil 12.2.1 Speichergröße von Zeigern
Pfeil 12.3 Zeigerarithmetik
Pfeil 12.4 Zeiger, die auf andere Zeiger verweisen
Pfeil 12.4.1 Subtraktion zweier Zeiger
Pfeil 12.5 Typensicherung bei der Dereferenzierung
Pfeil 12.6 Zeiger als Funktionsparameter (call–by–reference)
Pfeil 12.6.1 Zeiger als Rückgabewert
Pfeil 12.7 Array und Zeiger
Pfeil 12.8 Zeiger auf Strings
Pfeil 12.8.1 Zeiger auf konstante Objekte (Read-only-Zeiger)
Pfeil 12.9 Zeiger auf Zeiger und Stringtabellen
Pfeil 12.9.1 Stringtabellen
Pfeil 12.10 Zeiger auf Funktionen
Pfeil 12.11 void-Zeiger
Pfeil 12.12 Äquivalenz zwischen Zeigern und Arrays
Pfeil 12.13 Der »restrict«-Zeiger


Galileo Computing - Zum Seitenanfang

12.11 void-Zeiger topZur vorigen Überschrift

Ein Zeiger auf void ist ein typenloser und vielseitiger Zeiger. Wenn der Datentyp des Zeigers noch nicht feststeht, wird der void-Zeiger verwendet. void-Zeiger haben den Vorteil, dass Sie diesen eine beliebige Adresse zuweisen können. Außerdem kann ein void-Zeiger durch eine explizite Typumwandlung in jeden anderen beliebigen Datentyp umgewandelt werden. Beispielsweise:

/* void_ptr1.c */
#include <stdio.h>
#include <stdlib.h>

int main(void) {
   int a = 10;
   char *string = "void-Zeiger";
   void *ptr;

   /* void-Zeiger auf Variable int a */
   ptr = (int *)&a;
   printf("ptr = %p a=%p\n",ptr,&a);
   /* void-Zeiger auf string */

   ptr = (char *)string;
   printf("ptr = %p string = %p\n",ptr,string);
   return EXIT_SUCCESS;
}

Natürlich sollten Sie darauf achten, dass Sie für das Casting einen Zeiger angeben und nicht etwa einen Datentyp:

/* Richtig */
ptr=(typ *)&ptr2;

/* Falsch: typ ist kein Zeiger, sondern eine Variable */
ptr=(typ)&ptr2;

Zwar wurde hier im Beispiel ein Cast von void * nach datentyp * gemacht, aber dies ist in C nicht unbedingt nötig – C++ allerdings macht sehr wohl einen Unterschied und braucht einen Cast von void * nach datentyp *.

Würden Sie im Beispiel oben die Casts entfernen und das Beispiel als C++-Projekt übersetzen (was bei vielen Compilern unter MS-Windows häufig voreingestellt ist), würde der Compiler eine Warnung ausgeben, wie beispielsweise:

[Warning]:
In function int main : invalid conversion from `void*' to ` int*`

Und genau diese Warnmeldung lässt viele Programmierer vermuten, dass etwas am Listing falsch sei und man den void-Pointer immer casten müsste. Sofern Sie Ihren Compiler nicht davon überzeugen können, dass Sie gern ein C-Projekt schreiben würden, sollten Sie meiner Meinung nach dem sanften Druck des Compilers nachgeben (auch wenn das Programm tut, was es tun soll und ohne Problem ausgeführt werden kann) und ihm sein Cast geben – da dies ja auch nicht unbedingt »falsch« ist. Schließlich zählt zu einem der oberen Gebote eines Programmierers, dass man niemals Warnmeldungen eines Compilers ignorieren soll.

Vorwiegend findet ein void-Zeiger Anwendung in Funktionen, die mit unterschiedlichen Zeigern aufgerufen werden können. Beispielsweise ist die Funktion memcmp() in der Headerdatei <string.h> folgendermaßen angegeben:

int memcmp (const void*, const void*, size_t);

Somit kann diese Funktion mit unterschiedlichen Zeigertypen verwendet werden, wie das folgende Beispiel zeigt:

/* void_ptr2.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void) {
   char str1[]="Hallo";
   char str2[]="Hallo";
   int num1[] = { 1,2,3,4,5,6 };
   int num2[] = { 1,3,5,7,9,1 };
   int cmp;
   /* Casts sind nicht unbedingt nötig. */
   cmp=memcmp( (char *)str1, (char *)str2, sizeof(str1));
   if(cmp ==0)
      printf("Beide Strings sind gleich\n");
   else
      printf("Die Strings sind nicht gleich\n");
   /* Casts sind nicht unbedingt nötig. */
   cmp=memcmp((int *)num1,(int *)num2, sizeof(num1)/sizeof(int));
   if(cmp == 0)
      printf("Der Inhalt der beiden Zahlenarrays ist gleich\n");
   else
      printf("Die Zahlenarrays sind unterschiedlich\n");
   return EXIT_SUCCESS;
}

Die Umwandlung in einen entsprechenden Zeigertyp findet mit einem einfachen Type-Casting statt – was auch hier nicht unbedingt nötig gewesen wäre (siehe den Abschnitt vor dem Listing).

Für einige ist es verwirrend, wie ein leerer Zeiger (void, dt. leer) einfach so in irgendeinen Datentyp gecastet werden kann, weil sie gelernt haben, dass int vier Bytes Speicher hat, double acht Bytes Speicher und void eben keinen. Dabei ist void eigentlich auch nicht ganz leer. Wenn Sie mit void den sizeof-Operator verwenden, erfahren Sie, dass void ein Byte an Speicher benötigt.

Aber erinnern Sie sich nochmals an den Anfang des Kapitels, bei dem Sie den sizeof-Operator auf alle Typen von Zeigern verwendet haben: Da habe ich gesagt, dass alle Zeiger, egal welchen Typs, einen Speicherbedarf von vier Bytes (32 Bit) haben. Mehr ist auch nicht erforderlich, um eine Speicheradresse zu speichern. Ebenso sieht es mit dem void-Zeiger aus. Dieser benötigt wie alle anderen Zeiger vier Byte Speicherplatz.

/* void_ptr3.c */
#include <stdio.h>
#include <stdlib.h>

int main(void) {
   void *void_ptr;

   printf("%d Byte\n", sizeof(void_ptr));
   return EXIT_SUCCESS;
}

Wollen Sie den Typ, auf den der void-Zeiger verweist, dereferenzieren, wird die Sache ein wenig komplizierter. Dafür benötigen Sie einen weiteren Zeiger:

/* void_ptr4.c */
#include <stdio.h>
#include <stdlib.h>

int main(void) {
   void *void_ptr;
   int wert = 10;

   void_ptr=(int *)&wert;
   *(int *)void_ptr = 100;
   printf("%d\n",wert);   /* 100 */
   return EXIT_SUCCESS;
}

Da der gecastete void-Zeiger allein noch nicht dereferenziert werden kann, wird hier einfach ein weiterer Zeiger verwendet:

*(int *)void_ptr = 100;

Jetzt denken Sie sicherlich darüber nach, welchen Vorteil eigentlich ein void-Zeiger hat? Bei dem Beispiel, in dem die Funktion memcmp() verwendet wurde, ist der Vorteil eigentlich schon klar. Anstatt für jeden Datentyp eine eigene Funktion zu schreiben, wird einfach der void-Zeiger verwendet, und der Funktion kann es egal sein, mit welchem Datentyp sie verwendet wird. Wichtig ist dabei nur, dass die Funktion (logischerweise) entsprechend universell geschrieben wurde. Sie können nicht einfach einer Funktion, die mit der Funktion strcmp() einzelne Strings vergleicht, als Argument die Anfangsadresse eines int-Arrays übergeben.



Ihr Kommentar

Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen.






<< zurück
  
  Zum Katalog
Zum Katalog: C von A bis Z

 C von A bis Z
Jetzt bestellen


 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps
Zum Katalog: Einstieg in C++






 Einstieg in C++


Zum Katalog: C++ von A bis Z






 C++ von A bis Z


Zum Katalog: C/C++






 C/C++


Zum Katalog: Shell-Programmierung






 Shell-Programmierung


Zum Katalog: Linux-UNIX-Programmierung






 Linux-UNIX-
 Programmierung


Zum Katalog: IT-Handbuch für Fachinformatiker






 IT-Handbuch für
 Fachinformatiker


Zum Katalog: Ubuntu GNU/Linux






 Ubuntu GNU/Linux


Zum Katalog: Coding for Fun







 Coding for Fun 


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo




Copyright © Galileo Press 2009
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Galileo Computing]

Galileo Press, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de