2016-08-17 1 views
-1

Laut "C - A Reference Manual" ist ein Lvalue ein Ausdruck, der sich auf ein Objekt bezieht, so dass das Objekt untersucht oder verändert werden kann.Sind diese Zeiger lvalues?

Zum Beispiel

int ranks[10]; 

sind dann ranks und ranks+3 lvalues? Da ranks (Zeiger auf das erste Element des Arrays) und ranks+3 (Zeiger auf das vierte Element des Arrays) beziehen sich auf Objekte, ich denke, sie sind lvalues ​​- oder sind es nicht lvalues?

+0

Mögliches Duplikat von [C Wie erkennt man rvalue und lvalue?] (Http: // stackoverflow.com/questions/11105284/c-how-to-identify-rvalue-and-lvalue) –

+1

C11-Entwurfsstandard n1570, * 6.3 Konvertierungen 6.3.2.1 L-Werte, Arrays und Funktionsbezeichner 3 Außer wenn es der Operand des sizeof-Operators ist , der _Alignof-Operator, oder unary & operator, oder ist ein String-Literal, das zum Initialisieren eines Arrays verwendet wird, ein Ausdruck, der hat type '' array of type '' wird in einen Ausdruck mit dem Typ '' pointer to type '' konvertiert Das verweist auf das Anfangselement des Array-Objekts und ist kein Lvalue. Wenn das Array-Objekt Registerspeicherklasse hat, ist das Verhalten nicht definiert. * – EOF

+0

Es hängt vom Kontext ab. Bitte geben Sie diesen Kontext an. – 2501

Antwort

2

In diesem Kontext sind die Namen keine lvalues, aber sie können mit * zur Bildung von lvalues ​​dereferenziert werden. Zum Beispiel:

int ranks[10]; 
// ranks = 42; <--- doesn't compile! error: assignment to expression with array type 
*ranks = 42; // OK: same as ranks[0] = 42 
//ranks+3 = 42; <--- error: lvalue required as left operand of assignment 
*(ranks+3) = 42; //OK: same as ranks[3] = 42 

This answer Listen den wenigen Fällen, in C, wenn der Name eines Arrays nicht Abklingen auf einen Zeiger auf das erste Element des Arrays. Auf der linken Seite einer Aufgabe ist keiner dieser Fälle. Daher ist in ranks = ..., ranks ist ein Zeiger auf das erste Element des Arrays (zerfällt, fungiert als). Sie müssen diesen Zeiger dereferenzieren (*ranks), um eines der Array-Elemente als lvalue zu erhalten.

Frag mich einfach nicht, was ein Lvalue ist. Ich weiß es, wenn ich es sehe. :)

Getestet auf gcc.

+0

Wenn ich eine Anweisung 'int x = 5' und 'Ränge = & x' hinzufüge, können wir nicht sagen, dass 'Ränge' auf Objekt verweisen? – Jin

+0

@Jin Wenn 'ranks'' int ranges [10] 'ist, wird' ranks = & x' nicht kompiliert. Es würde für 'int * ranks;' kompilieren. Dies ist eine der Situationen, in denen Arrays und Zeiger nicht perfekt austauschbar sind. – cxw

+0

@Jin: Sie können nicht zuweisen "Ränge"; Array-Ausdrücke können nicht das Ziel eines Zuweisungsoperators sein. –

3

ranks+3 ist kein Lvalue aus dem gleichen Grund, 1+3 ist kein Lvalue; das Ergebnis ist einfach ein numerischer (Zeiger) Wert, keine Referenz auf ein Objekt.

anders ausgedrückt, wenn das Ergebnis der ranks + 30xdeadbeef ist, können Sie nicht

0xdeadbeef = 10; 

aus dem gleichen Grund schreiben Sie nicht

4 = 10; 

jedoch *(ranks+3), schreiben ein L-Wert ist, weil Sie sind dereferencing dieser Zeigerwert; es ist das 4 th Element des ranks Arrays und entspricht ranks[3].

Ebenso ist ranks kein Wert, außer im Zusammenhang mit sizeof oder dem unären &-Operator. Da Array Ausdrücke „decay“, um Ausdrücke in den meisten Kontexten Zeiger, Sie wieder mit der Situation der

ranks = 10; 

gleichwertig zu

0xdeadbeef = 10; 

wieder aufzuwickeln, dann würden Sie zu dereferenzieren habenranks als entweder *ranks oder ranks[0], damit es ein Wert ist.

+0

Wenn ich 'int x = 10 'und' x = 0' zu meinem Code hinzufügen und Ihre Logik anwenden, da x ein int-Ausdruck ist, dann wäre 'x = 0' gleichbedeutend mit '10 = 0' ..? – Jin

+0

@Jin: Nein. Ich weiß nicht, wie ich es klarer machen soll. –

+0

Warum gilt Ihre Logik nicht für int Ausdruck? Ich denke, der Unterschied rührt von der Tatsache her, dass der Compiler einfach "Ränge" als "0xdeadbeef" auswertet, während der Compiler "x" nicht als "10" auswertet? – Jin