Structur array dynamisch, Pfeiloperator ist äquivalent wie Punktoperator?
-
Hallo,
ich habe ein C-Programm geschrieben dass mir alle Dateinamen im aktuellen Ordner in ein dynamisches Struktur Array speichert. Da es sich um eine dynamische Struktur handelt (also Zeiger auf die Strukut: *gefundeneDateinamen) muss ich ja den Pfeiloperator verwenden um auf die Variabeln zuzugreifen: gefundeneDateinamen->name
Was mich aber wundert, bzw. ich nicht verstehe ist dass auch der Punktoperator funktioniert: gefundeneDateinamen[count].name. Ich dachte dass der Punktoperatur dann verwendet wenn es sich um eine Normale Struktur handelt. Also kann ich mit beiden Varianten auf eine Zeiger Strukur zugreifen? Ist das äquivalent? Danke!
#include <stdio.h> #include <dirent.h> #include <string.h> #include <stdlib.h> #include <stdio.h> typedef struct{ char name[50]; }GefundeneDateinamen; int main(void) { int anzahlDateienMax = 10; int count =0; DIR *dirp; struct dirent *entry; GefundeneDateinamen *gefundeneDateinamen = (GefundeneDateinamen*)(malloc(anzahlDateienMax * sizeof(GefundeneDateinamen))); dirp = opendir("."); while ((entry = readdir(dirp)) != NULL) { if ( !strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..") ) { } else { //gefundeneDateinamen->name = (char*)malloc(sizeof(char)*(strlen(entry->d_name)+1)); // Dynamische allokation von aktuellerName strncpy (gefundeneDateinamen[count].name,entry->d_name, strlen(entry->d_name) ); gefundeneDateinamen[count].name[strlen(entry->d_name) ] = '\0'; // gefundeneDateinamen->name ist gleich wie gefundeneDateinamen[count].name? printf("%s\n",gefundeneDateinamen[count].name ); printf("%s\n",gefundeneDateinamen->name ); count++; } } closedir(dirp); return(0); }
-
Das liegt daran, daß generell ein Arrayzugriff
array[n]
äquivalent zu*(array + n)
ist, d.h. es findet schon eine Dereferenzierung statt (so daß man dann den Punktoperator zum Zugriff auf die Struktur verwendet kann).
Und der Pfeiloperatorpointer->x
ist wiederum äquivalent zu(*pointer).x
.
Sofern du den Zeiger nicht in deiner Schleife veränderst, gibt alsoprintf("%s\n",gefundeneDateinamen->name )
immer den gleichen (d.h. ersten) Dateinamen des Ordners aus.PS: Bedenke, daß du bei deinem Code vor dem
strncpy
die Länge (max. 50) vorher überprüfen solltest, um keinen Speicherüberschreiber zu haben.
-
Achso , du meinst vermutlich so etwas:
if(strlen(entry->d_name)<50)
Wie ist das eigentlich wenn ich in der Struktur selbst einen char Pointer verwende? Also
char *name;
anstattchar name[50];
Dann muss ich in meiner while Schleife bei jedem Durchgang für name (mit malloc) Speicher reservieren?
Und ich muss jeden Zeiger um 1 so erhöhen:(gefundeneDateinamen+count)
Es funktioniert zwar so aber ist mein Code so auch korrekt? (Also ohne irgendwelchen Buffer overflow?)
#include <stdio.h> #include <dirent.h> #include <string.h> #include <stdlib.h> #include <stdio.h> typedef struct{ char *name; }GefundeneDateinamen; int main(void) { int anzahlDateienMax = 10; int count =0; DIR *dirp; struct dirent *entry; GefundeneDateinamen *gefundeneDateinamen = (GefundeneDateinamen*)(malloc(anzahlDateienMax * sizeof(GefundeneDateinamen))); dirp = opendir("."); while ((entry = readdir(dirp)) != NULL) { if ( !strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..") ) { } else { if(strlen(entry->d_name)<50) { (gefundeneDateinamen+count)->name = (char*)malloc(sizeof(char)*(strlen(entry->d_name)+1)); strncpy ((gefundeneDateinamen+count)->name,(entry->d_name), strlen(entry->d_name)+1 ); (gefundeneDateinamen+count)->name[strlen(entry->d_name) ] = '\0'; printf("%s\n",(gefundeneDateinamen+count)->name ); count++; } } } closedir(dirp); return(0); }
-
Ja, so ist es jetzt [überwiegend] korrekt (aber dann brauchst du auch die Abfrage auf
< 50
nicht, da du ja dynamisch Speicher allozierst).
Du solltest allerdings nur einmaligstrlen(...)
berechnen und in einer lokalen Variable speichern und benutzen.
Außerdem ist die... = '\0'
-Zeile überflüssig, da du in der Zeile vorher ja das Nullterminalzeichen schon mitkopierst (wegenstrlen(...) + 1
).
Und ich habe zwar geschrieben, daß die Ausdrücke äquivalent sind, jedoch ist eher unüblich die Schreibweise(pointer+count)->x
zu verwenden. Stattdessen wird (auch aus Performancegründen) eine lokale Zeigervariable benutzt und erhöht:char *p = gefundeneDateinamen; while (...) { // ... size_t len = strlen(strlen(entry->d_name); p->name = malloc(len + 1); // in C solltest du keinen Cast (hier: (char*) )verwenden! strncpy(p->name, entry->d_name, len + 1); // ... p++; }
Und
sizeof(char)
ist auch (als Multiplikator) überflüssig, da es immer1
ist!PS: Außerdem solltest du noch die korrekte Speicherfreigabe ausprogrammieren (auch wenn der Speicher automatisch beim Beenden des Prozesses vom OS freigegeben wird), am besten als eigenständige Funktion - genauso wie das Einlesen.
Ich sehe gerade, daß du bisher auch die Anzahl der Dateien fest einprogrammiert hast - auch das solltest du entweder abfragen (und die Schleife beenden) oder aberrealloc
verwenden, um dynamisch den Speicher zu vergrößern.
-
Ok, danke für die Hilfe/Tipps.