Kopiert C das Element bei jedem Zugriff auf ein Array?

8

C kann keine Referenzen im Gegensatz zu C ++ zurückgeben. Heißt das, wenn Sie auf A[i] zugreifen, wird das Element beim Auswerten des Ausdrucks kopiert?

Wenn A beispielsweise ein Array von 10 int s ist, inkrementiert A[5]+=1; nur die temporäre Kopie, die bei der Auswertung von A[5] erstellt wurde, im Gegensatz zum C ++ Vektor, der das eigentliche sechste Element selbst inkrementiert?

    
Aaa Bbb 23.07.2017, 10:07
quelle

5 Antworten

12

C hat ein Konzept namens "lvalue", das eine Art Referenz ist. Es ist kein Typ (nicht Teil des Typsystems), aber bestimmte C-Ausdrücke sind 'lvalues', und nur solche Ausdrücke können der linke Operand einer Zuweisung (einschließlich einer Op-Zuweisung) oder ein Inkrement / Dekrement sein.

Da C keinen Operator überladen hat, muss im Typsystem nicht unterschieden werden, da niemals Dinge als rvalues ​​vs lvalues ​​deklariert werden müssen. Es war der Wunsch, das Überladen von Operatoren in C ++ hinzuzufügen, was zur Einführung von Referenztypen führte, um die Rvalue / Lvalue-Unterscheidung für überladene Operatoren klar zu machen.

    
Chris Dodd 23.07.2017 10:14
quelle
5

Wenn das wahr wäre, könnten Sie Arrays überhaupt nicht ändern und der Ausdruck A[5]+=1; hätte keine Auswirkung!

Wenn Sie dagegen ein skalares Argument an eine Funktion übergeben, verhält es sich wie eine Kopie, da es bei der Rückgabe nicht geändert wird. Aber ein Array, tatsächlich als ein Zeiger übergeben, wird nicht kopiert (das wäre unerträglich teuer) und kann bei der Rückkehr anders sein.

    
Yves Daoust 23.07.2017 10:26
quelle
4
  

tut A [5] + = 1; Erhöhen Sie nur die temporäre Kopie, die beim Auswerten von A [5]

erstellt wurde

Nein. A[5]+=1; bewirkt, dass das 6. Element von A um 1 erhöht wird.

Dies wird wahrscheinlich erreicht, indem A[5] in ein Register in der CPU kopiert wird, inkrementiert und der Wert zurückkopiert wird.

Hier ist ein Programm:

%Vor%

Hier ist der gcc-generierte x86-64-Assembler für A[5]+=1;

%Vor%

Das verschiebt DWORD PTR [rbp-28] in den 32-Bit-EAX-Akkumulator, fügt 1 hinzu und verschiebt es zurück zur selben Stelle.

DWORD PTR [rbp-28] identifiziert das 6. Element von A anhand seiner Position relativ zum (Ende des) Stack-Frames ( rbp ).

Der Punkt über Referenzen ist ein Red-Hering. Sowohl C als auch C ++ kompilieren zu Maschinencode (möglicherweise über Assembler). Welche anderen Funktionen die Sprachen haben, hat keinen Einfluss darauf, wie A[5]+=1; interpretiert oder kompiliert wird.

    
Persixty 23.07.2017 10:46
quelle
2

C kopiert immer ein Element, wenn lesen von einem Array mit A[i] , das heißt, wenn der Ausdruck A[i] ist ein "rvalue". Wenn Sie jedoch schreiben betrachten, hat C eine Vorstellung von "lvalue" -Ausdrücken, die im Wesentlichen eine eingeschränkte Teilmenge der Ausdruckssyntax sind, die als Ziel einer Zuweisung erscheinen dürfen:

%Vor%

In diesen Fällen werden die Ausdrücke " *X ", " X[i] " und " X.n " tatsächlich nicht zu Werten ausgewertet - sie haben die gleiche -Syntax wie die Ausdrücke, aber zur Vereinfachung nicht die gleiche Semantik . Sie können sich diese eher wie folgt vorstellen:

%Vor%

Oder denken Sie alternativ an C mit mehreren verschiedenen Zuweisungsoperatoren:

%Vor%

In beiden Fällen erhöht eine Zuweisung wie A[5] += 1 den Wert des sechsten Elements von A genau wie erwartet, was Sie wie folgt überprüfen können:

%Vor%     
Jon Purdy 23.07.2017 10:36
quelle
0

Nein, der Array-Index ist nur ein Zeiger, daher wird nur ein Speicherort anstelle des gesamten Arrays übergeben, und der Wert des tatsächlichen Speicherplatzes ist betroffen.

probiere den folgenden Code:

%Vor%

AUSGABE

    
Dharmendra Agrawal 23.07.2017 17:09
quelle

Tags und Links