myArray vs. &myArray



  • Bei meiner Beschäftigung mit C++ ist mir wieder etwas tolles aufgefallen. Dazu erstmal der Code:

    #include <iostream>
    #include <typeinfo>
    
    using namespace std;
    
    int main(void)
    {
        int myArray[5];
        for(int i = 0; i < 5; ++i)
        {
            myArray[i] = 0;
        }
        cout << &myArray << endl;
        cout << myArray << endl;
        cout << *(&myArray) << endl;
        cout << *myArray << endl;
        cout << typeid(&myArray).name() << endl;
        cout << typeid(myArray).name() << endl;
    }
    

    Die Ausgabe ist schonmal erstaunlich:

    0x2ff220d8
    0x2ff220d8
    0x2ff220d8
    0
    int (*)[5]
    int [5]
    

    Um das Dilemma zusammenzufassen:

    1. Wundert es mich schonmal, dass man auf
    myArray
    

    den Adressoperator anwenden kann, da es ja eigentlich kein lvalue ist, man kann ihm jedenfalls (ohne den Indexoperator) nichts zuweisen.

    1. Der Wert von
    &myArray
    

    und

    myArray
    

    ist identisch. Die Typen sind aber (offensichtlich) unterschiedlich.

    1. Das erstaunlichste überhaupt: Obwohl die Adressen, die von
    &myArray
    

    und

    myArray

    zurückgegeben werden, ja offensichtlich identisch sind, sind die Werte von

    *(&myArray)
    

    und

    *myArray
    

    unterschiedlich.

    Woran liegt das alles? Was passiert bei euren Compilern? Was sagt der Standard/ihr dazu?

    Felix

    P.S.: Ja, ich weiß, dass

    myArray
    

    das Selbe ist wie

    &(myArray[0])
    

    . ⚠ Trotzdem ist das oben gezeigte Verhalten, insbesondere

    &myArray
    

    komisch


  • Mod

    Phoemuex schrieb:

    1. Wundert es mich schonmal, dass man auf
    myArray
    

    den Adressoperator anwenden kann, da es ja eigentlich kein lvalue ist, man kann ihm jedenfalls (ohne den Indexoperator) nichts zuweisen.

    Die Frage des Zugriffs ist unerheblich. Benannte Objekte sind immer lvalues.

    1. Der Wert von
    &myArray
    

    und

    myArray
    

    ist identisch. Die Typen sind aber (offensichtlich) unterschiedlich.

    Genauer: Der Wert beider Pointer nachdem sie implizit in void* konvertiert wurden - nur das schaust du an. Es ist auch nicht überraschend: &myArray zeigt auf das gesamte array, (int*)myArray dagegen nur auf das erste Element - und C++ verlangt ausdrücklich, dass der Speicher in Arrays kontinuierlich (also ohne Löcher) und mit aufsteigenden Adressen belegt wird.

    1. Das erstaunlichste überhaupt: Obwohl die Adressen, die von
    &myArray
    

    und

    myArray

    zurückgegeben werden, ja offensichtlich identisch sind, sind die Werte von

    *(&myArray)
    

    und

    *myArray
    

    unterschiedlich.

    &myArray ist ein lvalue, dass auf das ganze Array verweist, also vom Typ int[5] - dafür gibt es keine Überladung mit cout, wohl aber für void - es folgt also eine implizite Konvertierung in int* und dann in void*; welches ausgegeben wird. Bei *myArray ist es anders: * benötigt ein rvalue als Argument; es gibt aber keine lvalue-zu-rvalue-Konvertierung für Arrays, an dessen Stelle tritt die Array-zu-rvlaue-Pointer Konvertierung, das Ergebnis ist ein rvalue int* welches dereferenziert wird, *myArray ist also ein lvalue vom Typ int (welches auf das erste Element des Arrays verweist) - und das wird dann ganz normal ausgegeben, denn für int existiert eine passende Überladung des >> Operators.



  • Vielen Dank 👍 Das lese ich mir jetzt noch 5 mal durch, bis ich es verstehe 😃

    Felix


Anmelden zum Antworten