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%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.
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.
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.
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
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.
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.