Wert in array ablegen



  • rüdiger schrieb:

    Weil es gegen die Strict-Aliasing-Regel verstößt und zB der GCC in dem Fall dann nicht das tut was du erwartest.

    Wie muss ich den gcc einstellen, damit er mir dort eine Warnung/Fehler ausgibt?

    Denn z.Zt. macht er genau das, was ich erwarte.

    #include <stdio.h>
    #include <stdint.h>
    
    int main()
    {
        uint32_t a = 0xffeeddcc;
        uint8_t b[4] = {0x11, 0x22, 0x33, 0x44};
    
        printf ("%02x %02x %02x %02x\n", b[0], b[1], b[2], b[3]);
    
       *(uint32_t *)b = a;
    
        printf ("%x\n", a);
        printf ("%02x %02x %02x %02x\n", b[0], b[1], b[2], b[3]);
    
        return 0;
    }
    

    Ausgabe:

    11 22 33 44
    ffeeddcc
    cc dd ee ff
    

    @Wutz
    Ich habe die Typen und Variablen vom TO genommen.



  • Wutz schrieb:

    Ach wirklich?

    IMHO und ohne nachgelesen zu haben darf man den Member der union lesen, den man geschrieben hat, ansonst -> UB.



  • Nein.
    Der (Lese)Wert der ganzen union ist zugesichert als der letztgeschriebene Elementwert, also z.B.

    union { int i;double d; } u={123};
    assert( 123==*(int*)&u ); /* o.g. Fall */
    assert( 123==u.i ); /* natürlicher Fall */
    assert( 123==u.d ); /* implementierungsabhängig, d.h. hier höchstwahrscheinlich false */
    


  • Wutz schrieb:

    Nein.
    Der (Lese)Wert der ganzen union ist zugesichert als der letztgeschriebene Elementwert, also z.B.

    union { int i;double d; } u={123};
    assert( 123==*(int*)&u ); /* o.g. Fall */
    assert( 123==u.i ); /* natürlicher Fall */
    assert( 123==u.d ); /* implementierungsabhängig, d.h. hier höchstwahrscheinlich false */
    

    u = { 123 } ist gleichbedeutend mit union { int i; double d; } u; u.i = 123 ??
    ... und dann weiter u.i "natürlich" und u.d UB?

    // edit: tausche ']' gegen '}' für ???? $



  • DirkB schrieb:

    rüdiger schrieb:

    Weil es gegen die Strict-Aliasing-Regel verstößt und zB der GCC in dem Fall dann nicht das tut was du erwartest.

    Wie muss ich den gcc einstellen, damit er mir dort eine Warnung/Fehler ausgibt?

    Denn z.Zt. macht er genau das, was ich erwarte.

    #include <stdio.h>
    #include <stdint.h>
    
    int main()
    {
        uint32_t a = 0xffeeddcc;
        uint8_t b[4] = {0x11, 0x22, 0x33, 0x44};
    
        printf ("%02x %02x %02x %02x\n", b[0], b[1], b[2], b[3]);
    
       *(uint32_t *)b = a;
    
        printf ("%x\n", a);
        printf ("%02x %02x %02x %02x\n", b[0], b[1], b[2], b[3]);
    
        return 0;
    }
    

    Ausgabe:

    11 22 33 44
    ffeeddcc
    cc dd ee ff
    

    @Wutz
    Ich habe die Typen und Variablen vom TO genommen.

    Du musst mit Warnings UND Optimierung (ich hatte es mal mit -O3, keine Ahnung bei welcher Stufe es genau anspringt) kompilieren.



  • Kannst du nicht lesen oder willst du nicht?
    Ich habe geschrieben es ist implementierungsabhängig und nicht es ist undefiniert.
    Da gibt es einen Unterschied, falls du es nicht weißt.
    Zur Syntax von union schaue dir die Spezifikation dazu an, die erkläre ich jetzt hier nicht auch noch.



  • Was bringt mir der Unterschied zwischen UB und imprementierungsspezifisch wenn ich nicht weiß, womit mein Code kompiliert wird?



  • DirkB schrieb:

    rüdiger schrieb:

    Weil es gegen die Strict-Aliasing-Regel verstößt und zB der GCC in dem Fall dann nicht das tut was du erwartest.

    Wie muss ich den gcc einstellen, damit er mir dort eine Warnung/Fehler ausgibt?

    Wie es halt mit UB ist. Manchmal haut es hin und manchmal eben nicht. In dem Fall hast du vermutlich Glück weil uint8_t "zufällig" ein char ist und für char das Strictaliasing nicht gilt.

    Daher mal uint16_t

    #include <stdio.h>
    #include <stdint.h>
    
    int main()
    {
        uint32_t a = 0xffeeddcc;
        uint16_t b[2] = {0x11, 0x22};
    
        printf ("%04x %04x\n", b[0], b[1]);
    
       *(uint32_t *)b = a;
    
        printf ("%x\n", a);
        printf ("%02x %02x\n", b[0], b[1]);
    
        return 0;
    }
    

    gcc -pipe -std=c99 -pedantic-errors -Wall -Wextra -Wstrict-aliasing=1 -O3 bar.c
    bar.c: In function ‘main’:
    bar.c:11:4: warning: dereferencing type-punned pointer might break strict-aliasing rules [-Wstrict-aliasing]



  • Welche Erkenntnis geben wir jetzt dem TO mit?

    Gibt es einen gleichwertigen (einzeiligen) Ersatz für sein Problem?



  • Für MSVC/MinGW oder einen Unix-cc:

    http://ideone.com/6twZv

    oder noch etwas kürzer:

    http://ideone.com/EL1kF


Anmelden zum Antworten