Warum und wie funktioniert ein char pointer?



  • inc7 schrieb:

    Wo ist definiert, dass const char [] l-value ist und z.B. ein int ein r-value?

    Hmmm? int ist ein lvalue. const int ist ein rvalue.



  • LValues und RValues haben mit Typen nichts zu tun. Es gibt ints sowohl als LValues, als auch als RValues.

    int i = 42; // 42 ist ein RValue, i aber ein LValue
    

    Grundsätzlich gilt: Alles, was einen Namen hat, ist ein LValue. Umgekehrt ist aber nicht alles, was keinen Namen hat, ein RValue.



  • Dann würde sich aber deine Aussage mit folgendem Code wiedersprechen:

    cout << &"Test" << endl;
    cout << &10 << endl;
    

    Geändert wurde nur der Typ von string nach int.



  • Nein, das widerspricht sich eben genau nicht. Stringliterale sind LValues.



  • 314159265358979 schrieb:

    Es gibt ints sowohl als LValues, als auch als RValues.

    Kannst du mir Beispielcode zeigen, wo ein int als LValue verwendet wird?

    314159265358979 schrieb:

    Stringliterale sind LValues.

    Und wo ist das in C++ definiert? Irgendwo muss ja (in der Headerdateien oder so?) stehen "stringliterale = LValue"



  • inc7 schrieb:

    Kannst du mir Beispielcode zeigen, wo ein int als LValue verwendet wird?

    i = 42;
    

    inc7 schrieb:

    Und wo ist das in C++ definiert? Irgendwo muss ja (in der Headerdateien oder so?) stehen "stringliterale = LValue"

    camper wirds dir sicherlich gleich nachschlagen. Kannst ja im Standard nachsehen.



  • inc7 schrieb:

    Kannst du mir Beispielcode zeigen, wo ein int als LValue verwendet wird?

    🙄

    inc7 schrieb:

    314159265358979 schrieb:

    Stringliterale sind LValues.

    Und wo ist das in C++ definiert?

    Im Standard?

    ISO/IEC 14882 third edition [expr.prim.general] 5.1.1.1 schrieb:

    A literal is a primary expression. Its type depends on its form (2.14). A string literal is an lvalue; all other literals are prvalues.



  • *loschmich*



  • 314159265358979 schrieb:

    Grundsätzlich gilt: Alles, was einen Namen hat, ist ein LValue.

    Hm...

    enum { ich_bin_ein_rvalue };
    template<int ich_auch> struct s {};
    

    Und this ist auch ein r-value.



  • Dann eben: Alles, was einen Namen hat und Stück Speicher zur Laufzeit bezeichnet, hat einen Namen.



  • Alles was einen Namen hat, hat einen Namen? 🙄



  • *ist ein LValue



  • Hmm, jetzt bin ich verwirrt!

    const int MeinName(0);
    

    Also, nach PI's Logik ist der Wert von MeinName kein solcher, der im Speicherplatz vorhanden ist, oder wat? MeinName ist doch ein Rvalue.


  • Mod

    Lvalues/Rvalues sind Ausdruckskategorien.
    Ein Bezeichner ist weder ein L- noch ein Rvalue.
    Ein (primärer) Ausdruck, der durch einen Bezeichner geformt wird, ist ein L- oder Rvalue, je nach Art des Bezeichners.



  • @Hacker: Natürlich ist das ein LValue, und natürlich hat der int auch Speicher. Dass der Compiler ihn wegoptimiert, ist ne andere Sache. Aber versuch doch mal, die Adresse davon rumzureichen, dann wird der int mit ziemlich großer Sicherheit nicht wegoptimiert.


  • Mod

    Hacker schrieb:

    Hmm, jetzt bin ich verwirrt!

    const int MeinName(0);
    

    Also, nach PI's Logik ist der Wert von MeinName kein solcher, der im Speicherplatz vorhanden ist, oder wat? MeinName ist doch ein Rvalue.

    Das ist zunächst mal eine Deklaration (und Definition), und kein Ausdruck. Also auch kein L- oder Rvalue. Und MeinName ist bloß der Bezeichner, der hier deklariert wird, nicht mehr und nicht weniger.
    Jede darauf folgende Verwendung dieses Bezeichners wäre ein Lvalue.



  • Das wird ja immer komplizierter. Inzwischen bin ich verwirrter als vorher. Ich versuche mal ganz konkret zu Fragen.

    Das Ausführen folgender Codezeile funktioniert fehlerfrei. Auf der Konsole wird die Adresse des Strings angezeigt.

    cout << &"Test" << endl;
    

    Laut typeid("").name() handelt es sich um ein const char [n] .

    cout << &10 << endl;
    

    funktioniert hingegen nicht.

    &10 klappt aus dem Grund nicht, weil 10 ein int ist und ein int ein rvalue ist. Bei &Test muss es sich dann um ein lvalue handeln. &Test kann aber auch ein rvalue sein, weil man einen string doch jederzeit einer anderen stringvaribale zuweisen kann. &Test = "test2" funktioniert aber auch nicht. Warum soll dann &Test ein lvalue sein?

    Dahinter muss doch eine einfache Logik stecken, die besagt wie und was ein rvalue und wie und was ein lvalue ist. Genau das ist das, wonach ich such. Wo gibt es sowas?



  • *seufz*

    Es kommt nicht auf die Typen an. Ob ein Objekt ein R- oder L-value ist, wird allein daraus bestimmt, in was für einem Typ von Ausdruck es gerade in diesem Moment vorkommt und ob da sObjekt ein Literal ist.

    Der Grund weswegen sich integer literale anders verhalten als string literale ist, dass im Standard vorgeschrieben ist, dass man diese string-literale im Ausführbaren Programm vorfinden können muss. Dadurch werden es Objekte, die man referenzieren kann und dadurch qualifizieren sie sich für L-Values. ein integer literal hingegen kann vom Compiler weg optimiert werden wie in:

    int x=1+2;

    Dem Compiler ist es erlaubt daraus:
    int x= 3;

    zu machen. Du kannst also nicht die Addresse von 1 holen, weil die 1 gar nicht im fertigen Programm enthalten ist.

    Merkregel:
    Etwas kann nur dann L-Value sein, wenn es nicht-temporären Speicher belegt
    integer literale belegen keinen Speicher
    string literale belegen Speicher
    Rückgabewerte von Funktionen belegen temporären Speicher.



  • @otze:

    int&& irr = 42;
    int* ptr = &irr;
    

    Und schon hab ich die Adresse von 42, stimmts? 😉



  • 314159265358979 schrieb:

    @otze:

    int&& irr = 42;
    int* ptr = &irr;
    

    Und schon hab ich die Adresse von 42, stimmts? 😉

    Nein. Du hast die Adresse von irr. '42' hat keine Adresse.

    Diese Dinger heißen aus gutem Grund "rvalue" references.


Anmelden zum Antworten