Defined Behavior



  • Ist das hier UB oder nicht?

    int a[3][3];
    a[0][6] = 9;
    


  • 'a' ist eine (in diesem Fall) lückenlose Reihe von 9 ints. (row-major-order)
    Da das subscripting im Standard mit einfacher Zeigerarithmetik erklärt wird und Du im Endergebnis auf a[6] zugreifst scheint mir das kein Problem.



  • Edit: Blök.



  • Hmm, ich weiß nicht ... das könnte so ein Fall von "undefiniert aber funktioniert überall" sein. Bin aber gerade zu faul, nachzugucken.



  • Ich denke das dürfte definiert sein. Definiert ist ja in jedem Fall, dass der Speicherbreich der Arrays zusammenhängend ist. Daraus folgt, dass auch das hier definiert ist:

    int a[3][3];
    int* p = a[0];
    p[6] = 9;
    

    Und wenn das definiert ist, sollte auch der Beispielcode okay sein.



  • Ist das dann trotzdem nicht eher ein "no go"?



  • Das ist durchaus definiert, und man kann damit lustige Späße treiben. So ist

    foo[1][-1];
    

    das letzte Element von foo[0]. Aber das ist noch harmlos:

    -1[1[foo]]
    

    macht das selbe.

    foo[bar] ist definiert als ((foo + bar)). foo[bar][baz] ist dementsprechend ((*(foo + bar) + baz)). Was mit dem einen geht, geht auch mit dem anderen.

    Das sind allerdings Dinge, die man nur mit gutem Grund und gut kommentiert benutzen sollte. Und selten.



  • seldon schrieb:

    -1[1[foo]]
    

    Ist das nicht das gleiche wie -(1[1[foo]]) ? Du meinst vermutlich (-1)[1[foo]] .



  • Ah. Richtig, mein Fehler.



  • Tim06TR schrieb:

    Ist das dann trotzdem nicht eher ein "no go"?

    Ja, das ist es. Wieso? Weil es keinen Sinn macht, statt a[1][2] a[0][6] bzw. a[6] zu schreiben. Entweder man möchte direkt ein eindimensionales Array, oder das würde ich als Bug einstufen weil die Indexe eben nicht zu den Array-Bounds passen (völlig unabhängig davon, ob das jetzt tatsächlich definiertes oder undefiniertes Verhalten ist, oder ob dieser Ausdruck damit auf ein Feldelement verweist). Das funktioniert so natürlich auch nur bei echten multidimensionalen Arrays...

    @seldon: Ja, der Operator ist (wie der Standard so schön sagt) neben seiner unsymmetrischen Syntax dennoch kommutativ. Trotzdem gibt es AFAIK keinen einzigen Grund, das auszunutzen... Also wieso selten und nicht nie, welchen guten Grund kann es da denn geben*?

    *Überladene Index-Operatoren sind hiervon ja ausgeschlossen, es geht lediglich um echte Arrays.



  • Nun ja,

    void foo(int *matrix, size_t x, size_t y) {
      ...
    }
    
    ...
    
    int m[3][3] = { { 1, 2, 3 },
                    { 4, 5, 6 },
                    { 7, 8, 9 } };
    
    foo(m[0], 3, 3);
    

    zum Beispiel. wobei man das eher in C- als in C++-Code haben will.

    (Geht übrigens auch umgekehrt)


Log in to reply