frage zu structs
-
hi,
was ist vom prinzip her sinnvoller beim arbeiten mit structs bzgl. char arrays:
typedef struct _A { char* name; }A; A a; scanf("%s",a.name);
oder diese hier:
typedef struct _B { char name[50]; }B; B b; scanf("%s", &b.name);
bei der 2ten variante komme ich ja leicht über die arraygrenze hinaus, oder? Bei der ersten wird der benötigete speicherbereich dann erst zur laufzeit geholt.
stimmt das so, oder is das mumpitz?
-
hi !
bei der ersten variante musst du selbst für genung speicherplatz sorgen.
dafür steht dir die funktion malloc und calloc zur verfügung.
den speicherplatz musst du auch selbst mit free wieder frei geben.a.name = malloc( 50 ); scanf( "%49s", a.name ); free( a.name );
bei der zweiten variante musst du dafür sorgen, das maximal 49 zeichen eingelesen werden. das 50ste ist der nullterminator.
wenn du vorher mit 0 initialisierst, brauchst du dich nicht um den nullterminator zu kümmern:B b={0};
um nicht über die grenzen des arrays zu kommen, kannst du so einlesen:
scanf("%49s", b.name ); // ohne adressoperator
oder so:
fgets( b.name, 49, b.name );
fgets hat die doofe angewohnheit, noch ein '\n' an den string zu hängen, wenn noch platz für ein zeichen übrig ist.
was sinnvoller ist, entscheidest du, bzw. die anforderung an dein programm.
wenn namen eingelesen werden sollen, halte ich es schon für sinnvoll, die anzahl der zeichen zu beschränken.
-
Böse Zungen behaupten dass die Deklaration mitteles char xyz[50] eine Sicherheitlücke aufmachen kann, weil man in gewissen Fällen die Rücksprungsadressen von Funktionen manipulieren kann.
Beispiel
void HalloWelt() { char xyz[50]; // entspricht: B xyz; xyz[51] = 0; // hier wird vermutlich der Framepointer überschrieben xyz[52] = 0; xyz[53] = 0; // hier wird vermutlich die Rücksprungadresse xyz[54] = 0; // .... }
Das Ganze dürfte ohne Probleme von den meisten Compilern kompiliert werden und führt zielstrebig zum Absturz, da man hier die eigene Rücksprungaddresse (hoffentlich) manipuliert hat.
In der Praxis ist es habe relativ egal was man nun nimmt. Man sollte aber schon aufpassen dass man nicht über die Arraygrenzen hinaus Werte schreibt.
Wenn man aber sehr große Datenmengen in ein struct packen will, würde ich die Variante des struct A empfehlen. Sonst kann es durchaus passieren dass der Stack überläuft, welcher je nachdem welcher Compiler/IDE man hat ein Größe von 1 Mb hat.
-
hioki schrieb:
hi,
typedef struct _A { char* name; }A; A a; scanf("%s",a.name);
d.h hier schreib ich unkontrolliert in den Speicher, weil ich vorher keinen speicher allociert hab?!
gut zu wissen....das hab ich früher gerne gemacht.
thx
-
korrekt;)
char *x;
ist ein zeiger auf den anfang einer zeichenkette. ohne malloc zeigt dieses X nach nirvana, und du könntest damit was kaputt machem;)
mit malloc wird im speicher ein freien platz gesucht, reserviert und der anfagst zeicehr auf x gesetzt
-
mr mumpitz schrieb:
fgets( b.name, 49, b.name );
fgets hat die doofe angewohnheit, noch ein '\n' an den string zu hängen, wenn noch platz für ein zeichen übrig ist.
es ist 1. keine doofe Angewohnheit und 2. '\n' wird nur angehängt, wenn es Platz gibt und \n gelesen wurde.
#include <stdio.h> int main(void) { char x[10]; fgets(x, 10, stdin); printf("x = \"%s\"\n", x); return 0; }
Bei der Eingabe 012345678 bekommt man kein \n
yanezp@mars:~> ./a 012345678 x = "012345678"