Array-Inkrementoperator in C

7

Ich verstehe die Ergebnisse des folgenden Codes nicht:

%Vor%

Warum erzeugt die zweite Funktion printf einen folgenden Fehler?

error: lvalue required as increment operand

    
user221458 02.10.2013, 04:58
quelle

7 Antworten

11

Teil-1:

Array-Namen sind konstant (nicht modifizierbarer L-Wert), Sie können dem Array-Namen einen Wert hinzufügen, ihn jedoch nicht ändern.

Ausdruck a + 2 ändert nicht a selbst, aber wenn Sie a++ ausführen, das äquivalent zu a = a + 1 ist, versuchen Sie, den Namen des Arrays --lvalue zu ändern. Der Ausdruck a++ im zweiten printf ist falsch - ein Beispiel für einen semantischen Phasenfehler. Lesen Sie folgende Sprachstandards:

  

6.3.2.1 L-Werte, Arrays und Funktionsbezeichner

     

724 Ein modifizierbarer L-Wert ist ein L-Wert ohne Array-Typ.   hat keinen unvollständigen Typ, kein const-qualifiziert   Typ, und wenn es eine Struktur oder Union ist, hat kein Mitglied   (einschließlich, rekursiv, jedes Mitglied oder Element aller enthaltenen   Aggregate oder Vereinigungen) mit einem Const-qualifizierten Typ.

     

729 Außer wenn es sich um den Operanden des Operators sizeof oder um den Operator unary & handelt,   oder ist ein String-Literal, das zum Initialisieren eines Arrays verwendet wird, ein Ausdruck, der   hat Typ "Array von Typ" wird in einen Ausdruck mit Typ konvertiert   "Zeiger auf den Typ", der auf das Anfangselement des Arrays zeigt   Objekt und ist kein lvalue .

Teil-2:

Beachten Sie, dass Array-Namen in den meisten Ausdrücken in der Adresse des ersten Elements abstürzen (lesen Sie einige Ausnahmen, bei denen Array-Name nicht in einen Zeiger auf das erste Element verfällt? geschickt beantwortet von @H 2 CO 3 ).

Wenn Sie a + 2 verwenden, ist sein Ergebnis die Adresse des dritten Elements (oder die Adresse des Elements am Index 2 ) Also a + 2 ist gleich wie &a[2] Es ist Adresse kein Wert am Index.

Um die Adresse zu drucken, verwenden Sie %p anstelle von %d und geben Sie die Adresse wie folgt in void* ein:

%Vor%

Um den Wert zu drucken, benötigen Sie den Verteidigungsoperator * wie folgt:

%Vor%

Teil-3:

  

Angenommen, a ist am Ort 2010 gespeichert, Ist die Ausgabe der ersten printf-Funktion 2012?

Nein, Zeigerarithmetik ist anders als Ganzzahlarithmetik. Wie wir wissen, zerfällt der Array-Name in den meisten Ausdrücken in die Adresse der Adresse des ersten Elements. Wenn Sie a + 2 verwenden, ist der Wert die Adresse des dritten Elements, das sich im Index 2 befindet. Angenommen, die int-Größe in Ihrem System beträgt 4 Byte, dann zeigt a + 2 stat auf den Standort 2018 entsprechend Ihrer Annahme, dass a address value 2010 ist.

Um zu verstehen, lesen 10.2 Pointer und Arrays; Pointer Arithmetic und Pointer Arithmetic .

    
Grijesh Chauhan 02.10.2013, 05:01
quelle
2
%Vor%

Angenommen, pa ist ein ganzzahliger Zeiger

A pointer is a variable, so pa=a and pa++ are legal. But an array name is not a variable; constructions like a=pa and a++ are illegal.

    
Gangadhar 02.10.2013 05:06
quelle
2

Ich denke, die erste Ausgabe hängt davon ab, wie der Integer-Typ in Ihrem Computer dargestellt wird. Wenn eine einzelne ganze Zahl 4 Bytes im Speicher belegt, sollte die Ausgabe 2018 sein, d. H. 2010 + 2 * 4. Der zweite Druck kann einen Kompilierungsfehler verursachen.

    
userwn 02.10.2013 05:25
quelle
2

Zuerst ruft dieses Programm undefiniertes Verhalten auf und ich bin wenig entmutigt, dass bei so vielen Antworten keiner von ihnen dies erwähnt. In beiden printf -Aufrufen ist Ihr Argument ein -Zeiger . Sie geben jedoch das Format als %d an, das erwartet wird, und int it sollte% p sein. Der C99-Entwurfsstandard im Abschnitt 7.19.6.1 Der fprintf Funktion auf die printf 's Abschnitt verweist für den Formatstring Absatz 9 sagt:

  

Wenn eine Konvertierungsspezifikation ungültig ist, ist das Verhalten nicht definiert. [...]

Zurück zu Ihrer Frage, der Ausdruck a++ erzeugt einen Fehler, weil postfix increment erfordert, dass es operand ist ein modifizierbarer lvalue ist Entwurfsstandard im Abschnitt 6.5.2.4 Postfix Inkrement- und Dekrementoperatoren Absatz 1 sagt ( Hervorhebung meins ):

  

Der Operand des Postfix-Inkrementierungs- oder Dekrementieroperators soll qualifiziert oder sein   unqualifizierter Real- oder Zeigertyp und soll ein modifizierbarer L-Wert sein .

können wir aus Abschnitt 6.3.2.1 Werte, Arrays und Funktionsbezeichner sehen Absatz 1 sagt:

  

[...] Ein modifizierbarer Lvalue ist ein Lvalue ohne Array-Typ [...]

    
Shafik Yaghmour 02.10.2013 12:31
quelle
1

Array-Speicheradressen bleiben konstant, Sie können sie also nicht ändern. Das machen Sie in einer ++ Anweisung. Der Compiler wird also einen Fehler ausgeben.

    
Manoj Kumar 02.10.2013 05:05
quelle
0

a ist keine Variable vom Typ int, es ist ein Zeiger auf eine ganze Zahl. Um es zu drucken, müssen Sie es zuerst dereferenzieren

%Vor%     
Abhimanyu saini 02.10.2013 06:40
quelle
0

Der Name des Arrays ist ein konstanter Zeiger und wird daher immer auf das 0. Element dieses Arrays zeigen. Es ist weder eine Variable, noch können wir ihr eine andere Adresse zuweisen, noch können wir sie durch Inkrementieren oder Dekrementieren verschieben. Daher

%Vor%     
Outlaw 01.01.2017 17:14
quelle

Tags und Links