forumnewbie hat geschrieben:Wenn ich das versuche:
Code: Alles auswählen
struct Address *mainAddress;
mainAddress = (struct Address *)malloc(sizeof(struct Address));
erhalte ich einen Fehler
"error: expected specifier-qualifier-list before mainAddress;"
Ich verstehe leider diesen Fehler nicht bzw. wie ich diesen beheben kann.
Hm...? Hast du vielleicht einen Abschreibfehler gemacht oder sonst etwas eingefügt? Hast du eventuell "Address" über ein typedef definiert? Also ich hab folgenden Code:
Code: Alles auswählen
#include <stdlib.h>
struct Address
{
char Street[64];
unsigned int houseNumber;
unsigned int zipCode;
char town[64];
};
int main( int argc, char *argv[] )
{
struct Address *mainAddress;
mainAddress = (struct Address *)malloc(sizeof(struct Address));
return 0;
}
Und das kompiliert so:
Code: Alles auswählen
$ gcc -o address address.c -Wall
address.c: In function ‘main’:
address.c:13:19: warning: variable ‘mainAddress’ set but not used [-Wunused-but-set-variable]
Also ohne Fehler (abgesehen von der offensichtlichen aber nicht relevanten Warnung).
forumnewbie hat geschrieben:Warum gibt malloc einen void-Zeiger zurück? Auf einer Webseite habe ich gelesen, dass ein void-Zeiger typenlos ist und somit auf jede Adresse zeigen kann - kann aber nicht jeder Zeiger auf jede Adresse im RAM zeigen? Ich dachte, dass malloc einfach die Adresse im Speicher zurückgibt, wo jetzt Platz reserviert wurde. Wofür benötige ich dann verschiedene Datentypen, um dort eine Adresse zu speichern? Ich glaube, dass ich das nicht richtig verstehe.
void-Zeiger sind typenlos und können wie jeder andere Zeige auf jede beliebige Stelle im RAM zeigen (Achtung: Nur darauf zeigen, für lesen und schreiben gibt es Einschränkungen!).
Warum gibt es verschiedene Typen für Zeiger? Führst du Operationen mit Zeigern durch, wird automatisch die Größe eines einzelnen Elements berücksichtigt. Hier ein kurzes Beispiel:
Code: Alles auswählen
#include <stdio.h>
int main( int argc, char *argv[] )
{
int *a = (int *)0x1000;
printf( "%p\n", a );
a++;
printf( "%p\n", a );
return 0;
}
Was würdest du als Ausgabe von diesem Programm erwarten? Die Ausgabe des Programms ist 0x1000 und 0x1004. Du inkrementierst den Zeiger, wodurch er auf das nächste Element zeigt. Das nächste Element liegt aber nicht an der nächsten Speicheradresse 0x1001, sondern genau 4 Byte weiter. Wobei in diesem Fall die 4 Bytes für die Größe eines Elements (also eines ints) stehen. Bei anderen Operationen verhalten sich Zeiger ähnlich. Es wird immer die Größe eines Elements berücksichtigt:
Code: Alles auswählen
#include <stdio.h>
int main( int argc, char *argv[] )
{
unsigned short int x = 0xFFFF; // 65535
printf( "%4X\n", x );
unsigned char *p = (unsigned char *) &x;
*p = 0;
printf( "%4X\n", x );
return 0;
}
Ausgabe:
Das ist eigentlich ein schlechtes Beispiel. Aber du siehst, dass hier nur 1 Byte zugewiesen wird. Der Zeiger soll ja schließlich auch auf ein unsigned char zeigen, das nur 1 Byte groß ist, nicht 2 Byte wie ein unsigned short int.
Du kannst malloc() nicht sagen für welchen Typ du Speicher reservierst. Das ist malloc() auch ziemlich egal. Du verlangst eine Anzahl in Byte und malloc() liefert dir (im Normalfall) einen entsprechenden Speicherbereich. Du bist dafür verantwortlich, dass du den Speicher richtig verwendest. Durch den void-Zeiger wirst du wie von cloidnerux bereits erwähnt dazu gezwungen dir Gedanken über deine Daten zu machen und zu wissen was dein Speicher darstellt.