2010-11-24 9 views
1
#include <iostream> 
using std::cout; 
using std::endl; 

int a[] = { 10, 20 }; 

int b[] = { 30, 40 }; 

int main(int argc, char ** argv) 
{ 
int * p = a; 

for (int i = 0; i < 4; i++) 
{ 
    cout << *(p + i) << endl; 
} 

return 0; 
} 

Warum funktioniert es?Zuweisung von Speicher für Arrays in MVSC++

+1

Sie sollten sich nicht auf dieses Verhalten verlassen. –

+0

Meinen Sie, dass das Programm nicht abstürzt? –

+0

Siehe auch: http://stackoverflow.com/questions/671703/array-index-out-of-bound-in-c und http://stackoverflow.com/questions/3658383/accessing-array-beyond-the- Limit –

Antwort

4

Dies ist ein klassisches Beispiel für undefined Verhalten. Undefined behaviour bedeutet nicht Absturz - es bedeutet undefined beaviour - es kann arbeiten, abstürzen, nicht arbeiten, nicht abstürzen, und fast alles andere

+0

Wir sind viele Tests in Microsoft Visual Studio C++ 2008 gemacht, und es ist Arbeit. –

+0

in g ++ Compiler funktioniert es nicht –

+0

@mr. Vavhovsky: Ja, aber erstens ist es nicht portierbar, und zweitens garantiert MSVC, irgendwo in der Dokumentation, dass zwei globale Array definiert wiederum zusammenhängende Speicher haben? Ich bezweifle das, deshalb ist dies noch undefiniertes Verhalten. Siehe meinen Link, um die Unterschiede zwischen implementation-defined und undefined –

0

Es funktioniert zufällig.

Ihr Code zeigt undefiniertes Verhalten und unter dem undefinierten Verhalten besteht auch die Möglichkeit, dass es scheinbar "funktioniert".

1

Es funktioniert (manchmal), weil der Compiler (manchmal - nun, oft) die Arrays nebeneinander im Speicher platziert. Beginnend mit einem Zeiger auf die erste Position im ersten Array können Sie (manchmal) beide Arrays durchlaufen, indem Sie einfach den Zeiger inkrementieren.

Die Tatsache, dass der Speicher auf diese Weise ausgelegt ist, ist keineswegs garantiert und ist nicht etwas, auf das sich ein "echtes" Programm verlassen sollte.

Da der Standard nicht angibt, wie sich der Compiler in dieser Situation verhalten soll, heißt er Undefined Behavior (UB). Einige Informationen here.

0

Meine Vermutung ist, dass Ihr Ausgang ist:

10 
20 
30 
40 

Ihr Code stützt sich auf undefiniertes Verhalten: in Ihrem Fall a und b erscheinen im Speicher zusammenhängend sein, aber das ist nicht garantiert.

Beim Erreichen des undefinierten Verhaltens kann alles passieren. Mit allem, was ich meine: es kann "arbeiten" oder es könnte abstürzen, oder es könnte eine Rakete nach Kuba starten.

+0

Danke alles! Ich verstehe, dass es ein undefiniertes Verhalten ist, aber ich möchte verstehen, warum Studio zusammenhängende Blöcke zuweisen? –

2

C und C++ überprüft zur Laufzeit nicht, auf welche Speicherbereiche Sie zugreifen möchten. Sie können auf Speicherzellen außerhalb Ihres Arrays zugreifen, und das wird funktionieren. Wenn Sie auf diese Weise auf Speicher zugreifen, den Sie kennen (Speicher, den der C++ - Standard oder Ihr Compiler Ihnen sagt, wie zugeteilt wird), wird alles gut funktionieren (Sie könnten das sogar absichtlich tun), sonst ist es ein Bug und Ihre Anwendung wird es tun unvorhersehbares Verhalten bekommen.

In Ihrem Fall bedeutet dies, dass a und b auf aufeinander folgenden Speicherzellen sind. Wie auch immer, das hängt nur von Ihrem Compiler ab. Ihr Code funktioniert möglicherweise nicht mit anderen Compilern, mit verschiedenen Versionen Ihres Compilers oder sogar mit Ihrem Compiler, wenn Sie andere Kompilierungsoptionen verwenden.

0

Da der Compiler b richtig a im Speicher reservieren. Versuchen Sie, die tatsächliche Adresse a, b und p für jede Schleife Iteration zu drucken, und Sie werden es ziemlich schön sehen. Das passiert normalerweise bei Variablen, die in aufeinanderfolgenden Zeilen deklariert werden. Aber können Sie diesem nicht vertrauen. Compileroptimierungen könnten etwas anderes tun. Wenn Sie darauf vertrauen müssen, dass der für zwei Variablen zugewiesene Speicher zusammenhängend ist, verwenden Sie struct.

0

Es funktioniert, weil Ihr Compiler Speicher für a und b in einer Weise reserviert hat, die b unmittelbar hinter a ist. Dies ist nicht reproduzierbar und deshalb haben Sie undefined Verhalten.

Fügen Sie einfach eine andere Variable zwischen a und b, verwenden Sie einen anderen Compiler, oder (mein Favorit :) benennen Sie die Variablen. Ich habe einen Compiler gesehen, der die Variablen in alphabetischer Reihenfolge anordnet.

Ihr Code "funktioniert" zufällig.

0

Dies ist ein undefiniertes Verhalten, daher wird es im Allgemeinen nicht funktionieren. Ein gutes Beispiel dafür, wo es nicht funktioniert, ist clang. Dieser Compiler ist intelligent genug, um b zu optimieren, wenn die Linkzeitoptimierung aktiviert ist.

Verwandte Themen