Overflow in bit fields

后端 未结 4 972
野趣味
野趣味 2021-02-13 04:48

can I trust that the C compiler does modulo 2^n each time I access a bit field? Or is there any compiler/optimisation where a code like the one below would not print out Overflo

4条回答
  •  终归单人心
    2021-02-13 05:10

    Yes. We can get the answer from assembly. Here is a example I code in Ubuntu 16.04, 64bit, gcc.

    #include 
    
    typedef unsigned int uint32_t;
    
    struct {
      uint32_t foo1:8;
      uint32_t foo2:24;
    } G;
    
    int main() {
        G.foo1 = 0x12;
        G.foo2 = 0xffffff; // G is 0xfffff12
        printf("G.foo1=0x%02x, G.foo2=0x%06x, G=0x%08x\n", G.foo1, G.foo2, *(uint32_t *)&G);
        G.foo2++; // G.foo2 overflow
        printf("G.foo1=0x%02x, G.foo2=0x%06x, G=0x%08x\n", G.foo1, G.foo2, *(uint32_t *)&G);
        G.foo1 += (0xff-0x12+1); // // G.foo1 overflow
        printf("G.foo1=0x%02x, G.foo2=0x%06x, G=0x%08x\n", G.foo1, G.foo2, *(uint32_t *)&G);
        return 0;
    }
    

    Compile it with gcc -S <.c file>. You can get the assembly file .s. Here I show the assembly of G.foo2++;, and I write some comments.

    movl    G(%rip), %eax
    shrl    $8, %eax    #  0xfffff12-->0x00ffffff
    addl    $1, %eax    # 0x00ffffff+1=0x01000000
    andl    $16777215, %eax # 16777215=0xffffff, so eax still 0x01000000
    sall    $8, %eax    # 0x01000000-->0x00000000
    movl    %eax, %edx  # edx high-24bit is fool2
    movl    G(%rip), %eax   # G.foo2, tmp123
    movzbl  %al, %eax   # so eax=0x00000012
    orl     %edx, %eax  # eax=0x00000012 | 0x00000000 = 0x00000012
    movl    %eax, G(%rip)   # write to G
    

    We can see that compiler will use shift instructions to ensure what you say.(note: here's memory layout of G is:

    ----------------------------------
    |     foo2-24bit     | foo1-8bit |
    ----------------------------------
    

    Of course, the result of aforementioned is:

    G.foo1=0x12, G.foo2=0xffffff, G=0xffffff12
    G.foo1=0x12, G.foo2=0x000000, G=0x00000012
    G.foo1=0x00, G.foo2=0x000000, G=0x00000000
    

提交回复
热议问题