dereferenziert &array[X]?


  • Mod

    Ich bin ziemlich sicher, dass der Standard keine "wilden Zeiger" kennt.



  • Swordfish schrieb:

    Ich weiß nicht, wie's der Standard damit hält, aber kein Compiler wird bei

    array[ sonstwas ];
    

    dereferenzieren. Wofür denn auch?

    Um auf das Element zuzugreifen. array[index] ist nur eine andere Schreibweise für *(array+index) .

    Bisher hat niemand ein Argument dafür geliefert, warum es dem Compiler verboten sei, bei &array[index] zu dereferenzieren. Das kann nämlich selbst bei gültigem Index eine Rolle spielen.

    Sone schrieb:

    &array[size + 1] ist laut Standard dasselbe wie &(*(array + (size + 1))). Und da steckt halt die Dereferenzierung eines wilden Pointers drinnen.

    Nicht nur die Dereferenzierung, auch das Lesen eines Zeigers jenseits des Arrays ist UB -- bis auf die von hustbaer genannte Ausnahme.

    < 💡 >



  • glühbirne schrieb:

    Swordfish schrieb:

    Ich weiß nicht, wie's der Standard damit hält, aber kein Compiler wird bei

    array[ sonstwas ];
    

    dereferenzieren. Wofür denn auch?

    Um auf das Element zuzugreifen. array[index] ist nur eine andere Schreibweise für *(array+index) .

    Du hast nichts verstanden. Eine Anweisung wie diese hat keinen Effekt, weil sie überhaupt nichts tut. Es gibt keine Berechnung o. ä., für die der Dereferenzierte Wert gebraucht wird. Es wird einfach rausoptimiert, alles andere wäre Wahnsinn.

    glühbirne schrieb:

    Sone schrieb:

    &array[size + 1] ist laut Standard dasselbe wie &(*(array + (size + 1))). Und da steckt halt die Dereferenzierung eines wilden Pointers drinnen.

    Nicht nur die Dereferenzierung, auch das Lesen eines Zeigers jenseits des Arrays ist UB -- bis auf die von hustbaer genannte Ausnahme.

    Danke 👍



  • Sone schrieb:

    Du hast nichts verstanden. Eine Anweisung wie diese hat keinen Effekt, weil sie überhaupt nichts tut. Es gibt keine Berechnung o. ä., für die der Dereferenzierte Wert gebraucht wird. Es wird einfach rausoptimiert, alles andere wäre Wahnsinn.

    Ne, wie üblich hast du nichts verstanden.

    So eine Optimierung ist Qualität der Implementierung, der C++-Standard schreibt sie nicht vor.

    < 💡 >



  • hustbaer schrieb:

    &array[size + 1] ist nicht OK, weil man - abgesehen von der "one past last element" Ausnahme oben und NULL - nur Zeiger auf gültige Objekte bilden darf.

    Moment, das würde ja heißen, dass dieses Programm eigentlich nicht standardkonform wäre 😮:

    #include <iostream>
    #include <ostream>
    int main()
    {
      int const* const Zgr_F = reinterpret_cast<int*>(0x0); //Var. 1
      int const* const Zgr_W = reinterpret_cast<int*>(0xF2A911E); //Var. 2
        //So, beide Zeiger dürften ins Nichts zeigen
      int const Y = 20;
      int const* Zgr_M = &Y + 7372; //Var. 3
        //Und auch dieser zeigt wohl irgendwohin
      std::cout << Zgr_F << Zgr_W << Zgr_M << std::endl;
        //Gegen das Wegoptimieren
    }
    

    Ich hoffe jetzt mal, dass hattest du irgendwie anders gemeint …



  • Eben, genau das hab ich mich auch gefragt.



  • camper schrieb:

    Ich bin ziemlich sicher, dass der Standard keine "wilden Zeiger" kennt.

    Ich hoffe es, aber frag' hustbaer!?

    glühbirne schrieb:

    Sone schrieb:

    [...]

    [...] So eine Optimierung ist Qualität der Implementierung, der C++-Standard schreibt sie nicht vor.

    . o O ( Ausnahmsweise ... )
    Nirgends im Standard steht, daß ein Compiler bei einem ill-formed Programm aua schreien muss. Besonders nicht, wenn die evtl. nicht Standardkonforme expression durch Optimierung garnicht übersetzt wird. So what's the point?


  • Mod

    Vielleicht solltet ihr euch erst mal überlegen, was genau unter Dereferenzierung verstanden werden soll.

    x[y]
    

    ist definitionsgemäß identisch zu

    *(x+y)
    

    sofern keine klassenspezifische Überladung im Spiel ist (5.2.1/1).

    array[size]
    

    ist also identisch zu

    *(array+size)
    

    Die Addition verursacht erst einmal ein Array-zu Zeiger-Verfall, das Ergebnis ist ein Zeiger auf das erste Element des Arrays (3.10/2 i.V.m. 4.2); sowie ein l- zu rvalue-Konvertierung für size.

    Das Ergebnis der Addition ist ein Zeiger, der "1 hinter das letzte Element des Arrays" zeigt (5.7/5). Ein gültiger Zeiger im übrigen (3.9.2/3).

    Die Indirektion per * stellt ansonsten keine weiteren Bedingungen, ist also in jedem Fall zulässig, sofern der Zeiger gültig ist (C++ ist hier weniger streng als C) (5.3.1/1). Das resultierende lvalue kann nat. nur eingeschränkt verwendet werden (4.1).


  • Mod

    Fast2_unreg schrieb:

    hustbaer schrieb:

    &array[size + 1] ist nicht OK, weil man - abgesehen von der "one past last element" Ausnahme oben und NULL - nur Zeiger auf gültige Objekte bilden darf.

    Moment, das würde ja heißen, dass dieses Programm eigentlich nicht standardkonform wäre 😮:

    #include <iostream>
    #include <ostream>
    int main()
    {
      int const* const Zgr_F = reinterpret_cast<int*>(0x0); //Var. 1
      int const* const Zgr_W = reinterpret_cast<int*>(0xF2A911E); //Var. 2
        //So, beide Zeiger dürften ins Nichts zeigen
      int const Y = 20;
      int const* Zgr_M = &Y + 7372; //Var. 3
        //Und auch dieser zeigt wohl irgendwohin
      std::cout << Zgr_F << Zgr_W << Zgr_M << std::endl;
        //Gegen das Wegoptimieren
    }
    

    Ich hoffe jetzt mal, dass hattest du irgendwie anders gemeint …

    Natürlich. Die erste Konvertierung erzeugt einen Nullpointer. Also kein Problem.
    Die zweite Konvertierung ist möglicherweise bereits undefiniert - die Abbildung von Integern auf Zeiger wird durch die Implementation vorgegeben, und es ist nicht vorgeschrieben, dass diese für jeden möglichen Wert definiert sein muss.
    Die Addition ist in jedem Fall undefiniert. Nicht-Array-Objekte dürfen für Zwecke der Zeigeraddition wie Arrays mit einem Element behandelt werden.


Anmelden zum Antworten