SZENARIO 1
int *nums = {5, 2, 1, 4}; // <-- assign multiple values to a pointer variable
printf("%d\n", nums[0]); // segfault
Warum ist dieser eine Fehler?
Sie haben nums
als Zeiger auf int deklariert - das nums
soll die Adresse einer ganzen Zahl im Speicher enthalten.
Sie haben dann versucht, nums
ein Array mit mehreren Werten zu initialisieren . Ohne auf viele Details einzugehen, ist dies konzeptionell falsch - es ist nicht sinnvoll, einer Variablen, die einen Wert enthalten soll, mehrere Werte zuzuweisen. In dieser Hinsicht würden Sie genau den gleichen Effekt sehen, wenn Sie dies tun:
int nums = {5, 2, 1, 4}; // <-- assign multiple values to an int variable
printf("%d\n", nums); // also print 5
In beiden Fällen (einem Zeiger oder einer int-Variablen mehrere Werte zuweisen) erhält die Variable dann den ersten Wert 5
, während die verbleibenden Werte ignoriert werden. Dieser Code entspricht, aber Sie erhalten Warnungen für jeden zusätzlichen Wert, der nicht in der Zuweisung enthalten sein soll:
warning: excess elements in scalar initializer
.
Wenn Sie der Zeigervariablen mehrere Werte zuweisen, wird das Programm beim Zugriff fehlerhaft ausgeführt. Dies nums[0]
bedeutet, dass Sie alles, was in Adresse 5 gespeichert ist, buchstäblich zurückstellen . nums
In diesem Fall haben Sie keinen gültigen Speicher für den Zeiger zugewiesen .
Es ist erwähnenswert, dass es keinen Segfault für den Fall gibt, dass der Variablen int mehrere Werte zugewiesen werden (Sie dereferenzieren hier keinen ungültigen Zeiger).
SZENARIO 2
int nums[] = {5, 2, 1, 4};
Dieser ist kein Segfault, da Sie legal ein Array von 4 Ints im Stapel zuweisen.
SZENARIO 3
int *nums = {5, 2, 1, 4};
printf("%d\n", nums); // print 5
Dieser Fehler tritt nicht wie erwartet auf, da Sie drucken den Wert des Zeigers selbst - NICHT das, was er dereferenziert (was ein ungültiger Speicherzugriff ist).
Andere
Es ist fast immer zum Segfault verurteilt, wenn Sie den Wert eines Zeigers fest codieren wie diesen fest (da es die Aufgabe des Betriebssystems ist, zu bestimmen, welcher Prozess auf welchen Speicherort zugreifen kann).
int *nums = 5; // <-- segfault
Als Faustregel gilt also, immer einen Zeiger auf die Adresse einiger zugeordneter zu initialisieren Variablen , z.
int a;
int *nums = &a;
oder,
int a[] = {5, 2, 1, 4};
int *nums = a;