2009-04-27 4 views
5

Sorry, wenn dies ein noob Frage ist :(Zu viele Elemente in einem Array! ..? Nein

Stück C-Code

int array[5]; 
int cnt; 

for(cnt = 0; cnt <= 10; cnt+=1) 
{ 
     array[cnt] = cnt; 
} 

Sollte ein Fehler geben, richtig Adaequat Aber warum ist, dass es das scheint!? - In der ersten Zeile wird ein Array mit mehr als der doppelten Größe (11) definiert. Sie können später auch auf Array [5 bis 10] zugreifen. Das verwirrte mich. Es funktioniert nicht mehr, wenn Sie Array [4 oder weniger] definieren. ...

Vielen Dank im Voraus

Antwort

23

Es kann passieren, dass Sie mit Ihrem speziellen Compiler und Computer arbeiten, aber Sie sollten nicht darauf zählen.

Das Verhalten Ihres Codes gemäß der C-Sprachspezifikation ist undefined. Dies bedeutet, dass es möglicherweise das tut, was Sie hoffen, oder dass Ihr Computer abstürzen könnte, oder es könnte demons to fly out your nose verursachen.

Im Gegensatz zu höheren Sprachen wie Java und C# vertraut C Ihnen und führt keine expliziten Überprüfungen der Grenzen von Arrays durch. Sie sollen verantwortlich sein und nicht die Grenzen des Arrays überschreiten.

+3

+1 für nasale Dämonen-Verteidigung! – RBerteig

+2

@RBertig: Ich glaube nicht, dass "Fenstersturz" (Verteidigung ist kein Wort) bedeutet, was du denkst, was es bedeutet. Im Englischen wäre das der Akt, jemanden/etwas durch ein Fenster zu werfen. http://en.wikipedia.org/wiki/Defenestration –

+0

Ein Tippfehler in der Tat, aber die Wortwahl war absichtlich. Ich griff nach etwas, das mit "Dämonen" aussprach, die die richtige Menge eines Gefühls unerwarteter Vertreibung hatten. Es war eine Strecke, und möglicherweise hinter dem Bruchpunkt der Metapher ;-) – RBerteig

4

"Aber warum ist das?"

Denn so ist C.

Array-Grenzen werden zur Laufzeit nicht überprüft.

Das ist das „Gesetz des C“ ist

16

Dies nur „funktioniert“, wenn Ihre Definition von „Werk“ ist ein Synonym für „noch nicht abgestürzt“.

+2

+1: Ich muss diese Linie für meinen nächsten Codebericht "ausleihen" ;-) – RBerteig

+1

Gibt es einen anderen Definition von "Arbeiten"? – spiderman

+0

Was für ein tolles Zitat, danke! – Charlie

0

Sobald Sie das Ende des Arrays ausgeführt haben, überschreiben Sie den Speicher, den die Software nicht erwartet, und beschädigen den Heap. Ihre Software läuft möglicherweise weiter, aber sie wird sehr instabil sein!

0

Hängt davon ab, wie der Stapelspeicher gepackt ist. Außerdem überschreibt er diese Werte gerne und liest sie sogar, aber höchstwahrscheinlich korrumpiert er den Stapel.

5

Was Sie sehen, ist undefiniertes Verhalten, verursacht durch den Zugriff auf das Array mit einem ungültigen Index. Undefiniertes Verhalten bedeutet, dass alles passieren kann, einschließlich der korrekten Funktionsweise Ihres Programms.

2

Arrays in C werden zur Laufzeit nicht überprüft. Mit anderen Worten, Sie können ein Array der Größe N "definieren" und glücklich von dem Ende der Array-Grenze zugreifen. Wenn Sie über das Ende des Arrays hinausgehen, werden Sie Speicher irgendwo auf dem Stapel (oder dem Heap) löschen.

Sobald Sie irgendwo Speicher verloren haben, wird Ihr Programm wahrscheinlich abstürzen. Diese Abstürze können schwer zu finden sein, weil sie weit weg von dem Punkt, an dem Sie tatsächlich das Ende des Arrays überrannt haben, abstürzen könnten.

Normalerweise, wenn Sie Arrays in C deklarieren, ist es am besten, eine Art Konstante oder #define zu verwenden, um die Größe des Arrays zu markieren:

#define MAX_ELEMENTS 10 
int array[MAX_ELEMENTS]; 
int cnt; 
for(cnt = 0; cnt < MAX_ELEMENTS; cnt+=1) { 
    array[cnt] = cnt; 
} 

Wenn Sie Vergangenheit MAX_ELEMENTS im Array Zuordnung gehen, könnten Sie überschreiben Sie den Wert von cnt.Sie könnten eine andere Variable überschreiben. Alles hängt vom Compiler und der Codestruktur ab. Beachten Sie auch die Verwendung des <-Zeichens in der for-Schleife. C-Arrays sind 0-basiert, Sie müssen also prüfen, ob Sie weniger als und nicht weniger als oder gleich verwenden.

4

Ich möchte nur darauf hinweisen, dass dies alles undefiniert ist. Ihr Beispiel "funktioniert" in diesem speziellen Beispiel, weil sich beide Variablen auf dem Stapel befinden. Das ist die Adresse von cnt ist knapp unter dem Ende des Arrays. Wenn cnt erreicht cnt == 5 die Anweisung array [cnt] = cnt; schreibt nicht in den Speicher, der dem Array gewidmet ist, sondern direkt danach, wo die Adresse von cnt lag. Es ist nur Glück, dass es Ihren Schalter nicht ändert. Wenn cnt> 5 gibt es keinen Speicher für den Papierkorb und es wird nur in den "Stack void" geschrieben (weiß nicht das richtige Wort).

ein weiteres Beispiel, dies zu veranschaulichen:

int main(int ac,char **av) 
{ 
    int a[5]; 
    int cnt; 
    int cnt2=3; 

    for(cnt=0;cnt<7;cnt++) { 
     a[cnt]=cnt; 
     printf("%d %d %d\n", a[cnt], cnt, cnt2); 
    } 
} 

output:

0 0 3 
1 1 3 
2 2 3 
3 3 3 
4 4 3 
5 5 5 
6 6 5 

Die letzten zwei Schreibvorgänge der Schleife überschreibt die Stapeldaten nach a [] und ergeben kann sehr verwirrend Fehler. In diesem Fall wird das cnt2 verworfen.

+0

Schöne Abbildung. Leider kann ich hier nicht zwei beste Antworten markieren. : \ – spiderman

1

Array-Grenzen in C sind nicht unbedingt zur Laufzeit überprüft. Der Standard lässt es den Implern frei, dies zu tun, wenn sie sich dafür entscheiden oder nicht - das ist Teil dessen, was undefined ist. Bei einer Implementierung mit Fat-Pointern könnte die Stichprobe tatsächlich eine Art von Fehler verursachen.

Verwandte Themen