Frage zu Arrays



  • @Michael E.:
    Beleg hab' ich keinen dafür zur Hand.

    Aber...

    data[size] wird erstmal zu *(data + size) .
    D.h. als erstes kommt mal der Array-to-Pointer decay von "data", und danach die Addition. Beides noch unproblematisch. Danach kommt der böse *.

    Nur das Ergebnis davon ist erstmal noch ne Lvalue (vom Typ T& wenn ich nicht ganz daneben liege). In &data[size] holen wir uns dann die Adresse von dieser Lvalue.

    Die Frage ist also: dürfen wir auch Lvalue-Referenzen auf "one past (the) last element" erzeugen? Ich sehe keinen Grund der dagegen spricht, also behaupte ich einfach mal: ja, dürfen wird 🙂

    EDIT:
    Hier auch zum gleichen Thema:
    http://stackoverflow.com/questions/988158/take-the-address-of-a-one-past-the-end-array-element-via-subscript-legal-by-the
    Siehe Antwort von Adam Rosenfield, Zitat aus §6.5.3.2, paragraph 3

    The unary & operator yields the address of its operand. If the operand has type ‘‘type’’, the result has type ‘‘pointer to type’’. If the operand is the result of a unary * operator, neither that operator nor the & operator is evaluated and the result is as if both were omitted, except that the constraints on the operators still apply and the result is not an lvalue. Similarly, if the operand is the result of a [] operator, neither the & operator nor the unary * that is implied by the [] is evaluated and the result is as if the & operator were removed and the [] operator were changed to a + operator. Otherwise, the result is a pointer to the object or function designated by its operand.



  • Caligulaminus schrieb:

    hustbaer schrieb:

    [..]der Standard sagt, dass man keine ungültigen Adressen erzeugen oder rumreichen darf.[..]
    [..]grosse dicke Ausnahme[..]
    [..]man darf die Adresse des "one past last element" erzeugen und auch rumreichen.[..]

    Hmmm... elegant is dann aber doch anders. Naja - gewachsene Systeme halt...

    Sagen wir einfach mal es ist praktisch 🙂



  • Michael E. schrieb:

    [..]kann er auch die Adresse von Barack Obama berechnen[..]

    Oder die meines Nachbarn...

    Meine Aussage ist: es wird nichts "ausgewertet" (i.e. dereferenziert) sondern nur die Adresse meines Nachbarn errechnet. Es findet also nichts gefährliches oder aufwendiges statt.



  • hustbaer schrieb:

    Sagen wir einfach mal es ist praktisch 🙂

    😃



  • Caligulaminus schrieb:

    Michael E. schrieb:

    [..]kann er auch die Adresse von Barack Obama berechnen[..]

    Oder die meines Nachbarn...

    Meine Aussage ist: es wird nichts "ausgewertet" (i.e. dereferenziert) sondern nur die Adresse meines Nachbarn errechnet. Es findet also nichts gefährliches oder aufwendiges statt.

    Man kann wohl schwer mit nicht-standard Vokabular argumentieren, was der Standard als UB definiert oder nicht.

    Das da ist z.B. UB:

    void foo()
    {
        int* p = new int; // OK
        int* p2; // OK
        delete p; // OK
        p2 = p; // BAM, oida - UB!
    }
    

    Das da IMO auch:

    void bar()
    {
        int* p; // OK
        int* p2 = p; // BIG BADABOOM, UB!
    }
    

    Nach deiner Argumentation dürfte in beiden Fällen nix passieren.
    Laut Standard ist trotzdem beides UB, da man nur Zeigerwerte auf gültige Objekte (bzw. wieder mit der "one past last" Ausnahme) rumreichen darf.



  • hustbaer schrieb:

    The unary & operator yields the address of its operand. If the operand has type ‘‘type’’, the result has type ‘‘pointer to type’’. If the operand is the result of a unary * operator, neither that operator nor the & operator is evaluated and the result is as if both were omitted, except that the constraints on the operators still apply and the result is not an lvalue. Similarly, if the operand is the result of a [] operator, neither the & operator nor the unary * that is implied by the [] is evaluated and the result is as if the & operator were removed and the [] operator were changed to a + operator. Otherwise, the result is a pointer to the object or function designated by its operand.

    Klingt stichhaltig für C (auch wenn ich aus dem "except that the constraints on the operators still apply" noch nicht so ganz schlau werde). Wahrscheinlich kann man davon ausgehen, dass es dann in C++ ebenso legal ist. Danke für die Recherche.



  • Oops, mir ist gar nicht aufgefallen dass das aus dem C99 Standard und nicht dem C++ Standard ist. Hihi. War keine Absicht 🙂



  • Ist hustbaer Österreicher(Wiener?)? 😮



  • 314159265358979 schrieb:

    Ist hustbaer Österreicher(Wiener?)? 😮

    Österreicher ja, Wiener nein.
    Wieso, wegen des "BAM, oida"? Das schreib ich nur weil ich es witzig finde, bin aber kein angehöriger der Gruppe die sich neuerdings als "Krocha" bezeichnet (früher auch als "Dumme Proleten" bekannt - k.A. wieso die nen neuen Namen erfinden mussten 🤡).



  • Ja, genau deswegen. Krocha gabs bei uns vor geschätzt 4 Jahren zu hauf. Wobei "Dumme Proleten" es wohl wirklich besser trifft. 🤡



  • Krocha sind doch schon wieder sowas von gestern... :p

    Ich konnte in meinem Draft des C++ Standard nichts entsprechendes entdecken. Ich denk mal, wenn man's ganz sicher haben will sollte man wohl &vector[0] + size machen. Mag natürlich sein dass das im echten Standard anders steht, vermutlich aber nicht. Evtl. sollte man das reporten?



  • Waaaaaaah, wo ist camper wenn man ihn braucht? 🙂





  • Der Accountlose Benutzer hat jetzt einen Account^^

    Ich werde einfach data + size benutzen. Mir war vorher nicht klar, dass man das so schreiben kann.

    Ich hab noch eine andere Frage:
    Wenn ich einen vector mit

    vector<T> (data, &data[size]);
    

    erzeuge, werden dann die Daten kopiert? Und wird beim deleten des Vectors auch das data-Array gelöscht?



  • Ramanujan schrieb:

    Wenn ich einen vector mit

    vector<T> (data, &data[size]);
    

    erzeuge, werden dann die Daten kopiert?

    Ja.

    Und wird beim deleten des Vectors auch das data-Array gelöscht?

    Nein, die existieren dann völlig unabhängig voneinander.



  • Ramanujan schrieb:

    Der Accountlose Benutzer hat jetzt einen Account^^

    Ich werde einfach data + size benutzen. Mir war vorher nicht klar, dass man das so schreiben kann.

    Ich hab noch eine andere Frage:
    Wenn ich einen vector mit

    vector<T> (data, &data[size]);
    

    erzeuge, werden dann die Daten kopiert? Und wird beim deleten des Vectors auch das data-Array gelöscht?

    Heißt du nur Ramanujan, oder kennst du Srinivasa Ramanujan?
    Das geht IMO auch schöner:

    vector<T> (data, data + size);
    

    Dieser Konstruktor erwartet ein start-end Iteratoren-Paar. Die Werte des zweiten ersten und aller zwischen den beiden liegenden Iteratoren werden kopiert, weswegen, wie Michael Ende schon sagte, der Vector keinen Einfluss auf das eigentliche Array hat, AFAIK werden die beiden Iteratoren implizit zu const gecastet. Du kannst diesen Konstruktor wunderschön benutzen, um Container untereinander Daten austauschen zu lassen:

    std::vector<int> a(list.begin(), list.end());
    


  • Hacker schrieb:

    Die Werte des zweiten und aller zwischen den beiden liegenden Iteratoren werden kopiert

    Der "Wert" des zweiten Iterators wird nicht kopiert. Denn er zeigt auf das erste Element, das nicht mehr kopiert werden soll.

    Michael Ende

    Michael Ende ist tot.

    AFAIK werden die beiden Iteratoren implizit zu const gecastet.

    Warum sollte das passieren?



  • Michael E. schrieb:

    Hacker schrieb:

    Die Werte des zweiten und aller zwischen den beiden liegenden Iteratoren werden kopiert

    Der "Wert" des zweiten Iterators wird nicht kopiert. Denn er zeigt auf das erste Element, das nicht mehr kopiert werden soll.

    Flüchtigkeitsfehler, editiert 🕶

    Ich dachte, die iteratoren wären const? Wenn die Werte nur kopiert werden sollen, dann kann er ja auch const sein (auch wenn ich weiß, dass es nicht so ist)?



  • Ein Iterator, der const ist, lässt sich nicht inkrementieren.



  • 314159265358979 schrieb:

    Ein Iterator, der const ist, lässt sich nicht inkrementieren.

    Gut! Aber der zweite kann doch const sein? Die vergleichsoperatoren sind doch auch für konstante Objekte?


Anmelden zum Antworten