Wird ein Array-Argument an eine Funktion übergeben, nicht an einen konstanten Zeiger?

7

Betrachten Sie den Code:

%Vor%

Denken Sie jetzt darüber nach:

%Vor%

Ich habe gehört, dass ein Array einem konstanten Zeiger entspricht und nicht inkrementiert werden kann, da es kein Lvalue ist ...

Warum wird dann der erste Code kompiliert, weil Array-Argumente für Funktionen als Zeiger übergeben werden, d. h. T [] wird zum Übergeben in T * umgewandelt. Also übergibt foo (a) a als Zeiger.

Aber wird es nicht wieder zurück in T [] konvertiert, weil es wie folgt erklärt wird:

%Vor%     
bhuwansahni 01.04.2012, 08:45
quelle

7 Antworten

13

Wenn Sie ein Array als Argument an eine Funktion übergeben, verfällt es in einen Zeiger.
Das Ding, das Sie im Funktionskörper inkrementieren, ist also ein Zeiger, kein Array.

    
Alok Save 01.04.2012, 08:46
quelle
8

Dies ist ein ziemlich unglückliches Merkmal, das von der C-Sprache geerbt wurde, mit dem ziemlich ekligen Namen "Verfall". Da C einmal nicht erlaubte, Verbindungstypen nach Wert zu übergeben, entschieden sie sich dafür, es Programmierern zu erlauben, Arrays als Funktionsparameter-Typen zu spezifizieren, aber nur kosmetisch. Der Array-Typ zerfällt in einen Zeigertyp, der eine Art von Semantik für die Übergabe implementiert, die sich vom Rest der Sprache unterscheidet. Hässlich.

Zur Wiederholung (und andere haben das bereits gesagt), die Unterschrift

%Vor%

wird kurzerhand in

zerlegt %Vor%

... alles aus Gründen der Kompatibilität mit altem C-Code. Da Sie nicht alten C-Code schreiben, sollten Sie diese "Funktion" nicht nutzen.

Sie können jedoch eine Referenz sauber an ein Array übergeben. C ++ erfordert, dass die Größe des Arrays bekannt ist:

%Vor%

Jetzt a kann nicht innerhalb der Funktion geändert werden (editieren: seine Inhalte können natürlich - Sie wissen was ich meine), und nur Arrays der richtigen Größe können übergeben werden. Übergeben Sie für alles andere einen Zeiger oder einen übergeordneten Typ.

    
Potatoswatter 01.04.2012 09:14
quelle
4
  

Ich habe gehört, dass ein Array einem konstanten Zeiger entspricht

Sie können so darüber nachdenken, aber sie sind nicht gleichwertig.

Ein Array verfällt zu einem Zeiger, wenn es an eine Funktion übergeben wird, deshalb ist es innerhalb der Funktion gültig.

Nur weil die Signatur void foo(char a[]) ist, wird a nicht zu einem Array.

Außerhalb der Funktion ist es nur ein Array und Sie können keine Zeigerarithmetik darauf anwenden.

    
Luchian Grigore 01.04.2012 08:48
quelle
3

In C ++ wird jeder Funktionsparameter vom Typ "Array von T" als "Zeiger auf T" eingestellt. Probieren Sie diesen Code:

%Vor%

Sie sind in der Tat die gleiche Funktion.

Warum können wir ein Array-Argument als Zeigerparameter an eine Funktion übergeben? Nicht, weil ein Array einem konstanten Zeiger entspricht, sondern weil ein Array-Typ implizit in einen R-Wert des Zeigertyps konvertiert werden kann. Beachten Sie auch, dass das Ergebnis der Konvertierung ein R-Wert ist. Deshalb können Sie den Operator ++ nicht auf ein Array anwenden. Sie können diesen Operator nur auf einen L-Wert anwenden.

    
Cosyn 01.04.2012 10:08
quelle
1
  

Ich habe gehört, dass ein Array einem konstanten Zeiger entspricht und nicht inkrementiert werden kann, da es kein Lvalue ist ...

Fast.

Ein Array Ausdruck ist ein nicht modifizierbarer Lvalue ; es ist möglicherweise kein Operand für Operatoren wie ++ oder -- , und es ist möglicherweise nicht das Ziel eines Zuweisungsausdrucks. Dies ist nicht dasselbe wie ein konstanter Zeiger (dh ein Zeiger, der als T * const deklariert ist).

Ein Array-Ausdruck wird durch einen Zeigerausdruck ersetzt, dessen Wert die Adresse des ersten Elements des Arrays außer ist, wenn der Array-Ausdruck ein Operand von sizeof oder unary & ist Operatoren oder wenn der Array-Ausdruck ein String-Literal ist, das zum Initialisieren eines anderen Arrays in einer Deklaration verwendet wird.

Wenn Sie eine Funktion mit einem Array-Argument aufrufen, z. B.

%Vor%

Der Ausdruck a wird vom Typ "N-Element-Array von int " in "Zeiger auf int " konvertiert und dieser Zeigerwert wird an foo übergeben; Daher sollte der entsprechende Funktionsprototyp

sein %Vor%

Beachten Sie, dass im Zusammenhang mit einer Funktionsparameterdeklaration T a[] und T a[N] identisch mit T *a sind; In allen drei Fällen wird a als Zeiger auf T deklariert. Innerhalb der Funktion foo ist der Parameter arr ein Zeigerausdruck, der ist ein modifizierbarer L-Wert und kann somit dem Operanden von ++ und% zugeordnet sein und sein co_de% Operatoren.

Denken Sie daran, dass alle diese Konvertierungen im Array Ausdruck sind; Das ist die Array-ID oder ein anderer Ausdruck, der auf das Array -Objekt im Speicher verweist. Das Array-Objekt (der Teil des Speichers, der die Array-Werte enthält) wird nicht konvertiert.

    
John Bode 01.04.2012 16:08
quelle
1

Wenn Sie ein Array a [] an eine Funktion übergeben, übergibt es den Wert von 'a', eine Adresse, an die Funktion. Sie können es also als Zeiger in der Funktion verwenden. Wenn Sie ein Array in der Funktion deklarieren, ist 'a' konstant, weil Sie die Adresse im Speicher nicht ändern können.

    
wyq10 01.04.2012 09:03
quelle
-1

Innerhalb der Funktion ist a eine Adresse selbst, die auf eine lokale Variable zeigt. Sie können es erhöhen, weil es eine Adresse ist. Sie können auch so etwas tun:

%Vor%

Keine Fehler.

    
mtyurt 01.04.2012 09:26
quelle

Tags und Links