2016-06-11 32 views
-1

Kann ich drucken, wie ein Ausdruck ausgewertet wird?Gibt die Art eines Ausdrucks in C zurück, d. H., Ob es ein rvalue oder ein lval ist

Zum Beispiel, wenn ich wollte herausfinden, ob ein Wert als R-Wert ausgewertet wurde oder Lvalue ich den hypothetischen Code nennen würde:

int main() { 
    if(isrvalue(*(int *)4)) return 0; 
    else return 1; 
} 

Dies schafft Probleme wie wir "sind zu entdecken unten, dass die Typ 'eines Ausdrucks kann davon abhängen, ob er sich auf der rechten oder linken Seite des Zuweisungsoperators befindet. So würde der Test besser geeignet sein als

supports_lvalue(*(int *)4) 

Obwohl auch diese nur hypothetisch und kann nur verlassen werden, um das Spiel mit grundlegenden Beispielen.

Der Grund ist nur für Experimente, aber es könnte nützlich sein, im Debugging, wenn es möglich ist.

+2

Diese Frage ist meiner Meinung nach ziemlich unklar (ich konnte wirklich nicht verstehen, was Sie fragen). War im Begriff, downvote, aber wie Sie fragen, warum Sie downvotes bekommen, möchte ich erklären. –

+4

Ich glaube nicht, dass es eine Möglichkeit gibt, es in C zu tun. Sie müssten einen Compiler verwenden, mit dem Sie auf den AST einer bestimmten Kompilierungseinheit zugreifen können. Dennoch wäre es wahrscheinlich weniger nützlich, diese Informationen zu Debugging-Zwecken * zu kennen, als Sie vielleicht denken. Ein Programm, das einen R-Wert anstelle eines L-Wertes verwendet, wird trotzdem nicht kompiliert. –

+0

Was meinen Sie mit "ein Wert wurde als Rvalue oder Lvalue ausgewertet". Vielleicht fragen Sie, ob eine Lvalue-to-rvalue-Konvertierung angewendet wird, aber das hängt nur vom Kontext ab. Oder wollten Sie fragen, ob ein Ausdruck ein Wert ist oder nicht? –

Antwort

0

Nach den C Standard, section 6.3.2.1:

Ein lvalue ein Ausdruck ist (mit einem Objekttyp anders als void), die möglicherweise ein Objekt bezeichnet.

Obwohl dies eher vage ist, geht es weiter mit

Der Name '' lvalue '' stammt ursprünglich aus dem Zuweisungsausdruck E1 = E2, in der der linke Operand E1 erforderlich ist ein (modifizierbarer) Wert sein.

Und weiter mehr

Was manchmal ‚‚rvalue‘‘ genannt wird, ist in dieser Internationalen Norm als ‚‚Wert eines Ausdrucks‘beschrieben‘.

Was dies bedeutet für mich ist

Ein lvalue ein Wert, der Zuordnung unterstützt und ist auf der linken Seite des Zuweisungsoperators.

Ein rvalue ist ein beliebiger Wert nicht auf der linken Seite des Zuweisungsoperators.

So zum Beispiel

#include <stdio.h> 

int main() { 
    int array[1], *pointer, i = 42; 
    //     ^ ^-rvalue 
    //     lvalue 

    *array = i; 
    //^ ^-rvalue 
    //lvalue 

    pointer = array; 
    //^  ^-rvalue 
    //lvalue 

    printf("%p\t%d\n", pointer, *pointer); 
    //     ^-rvalues-^ 

    // causes segfault but compiles: 
    *(int *)4 = 2; 
    // ^ ^-rvalue 
    // lvalue 

    return 0; 
} 

Wie oben in den Kommentaren und die Frage zu beantworten voll

Sie haben würde einen Compiler verwenden, die Sie erhalten Zugriff auf die AST eines lässt Kompilierungseinheit.

2

Lvalue zeigt auf einen Speicherort, dem neue Werte zugewiesen werden können. Alle Variablen einschließlich const Variablen sind Lvalues. L-Werte bleiben über den Ausdruck hinaus bestehen, der sie verwendet. Auf der anderen Seite ist ein rvalue ein temporärer Wert, der nicht über den Ausdruck hinaus existiert, der ihn verwendet. Lvalues ​​können auf der linken oder rechten Seite des Zuweisungsoperators erscheinen. Aber Rvalues ​​können nie auf der linken Seite des Zuweisungsoperators erscheinen.

Kurz gesagt: Lvalues ​​sind Speicherbereiche und rvalues ​​sind Werte.

Beispiel:

int main(){ 

    int i = 10; 
    int j = 20; 

    int* ip; 
    int* jp; 


    /* ip and jp are pointer variables, hence L-VALUES. 
     they can appear BOTH sides of = operator. 
     as shown below. 
    */ 

    ip = &i; 
    jp = &j; 
    jp = ip; 

    /* values such as 1, 25, etc are Values, hence R-VALUES 
     they can appear only RIGHT side of = operartor 
     as shown below, 1 on left causes error not ip 
    */ 

    ip + 1 = &i; // invalid 
    ip = &i + 1; // valid, however printf("%d", *ip); might print a Garbage value 

    /* *ip and *jp are also L-VALUES, including *(ip + 1) or *(ip + 2) 
     they can appear both sides 

    */ 

    *ip = 1 + *jp; 

    return 0; 
} 

Sie einen Kompilierungsfehler erhalten, wenn Sie falsch lvalues ​​oder rvalues ​​verwenden.

+1

@JDoe Sie haben gesagt, dass Sie einen 'rvalue' in' lvalue' umwandeln können. Diese Aussage ist nicht korrekt. Es gibt keine solche Umwandlung. '* p',' * (p + 1) ',' * (p + 2) 'und' p' sind L-Werte. –

+0

Sie können auch überprüfen: http://stackoverflow.com/questions/17684476/is-p-an-lvalue-or-rvalue –

+0

p + 1 ist ein rvalue und wenn es mit dem unären "*" umfasst wird ein lvalue. –