C/C++- Fill variables using a single value


A more or less interesting C/C++ problem occured to me this day:

How do I initialize an integer with one part without using shifts. For example you have 0xFF and you want 0xFFFFFF.

Normally you would do something like this

int x = 0xFF << 16 | 0xFF << 8 | 0xFF

But how does it work without this runtime computation? And does it help you increase your performance? Of course not, but we'll see.

One could use arrays:

#define FILL(x,t) *(t*)(const unsigned char[]){x,x,x,0}

int main() {
    int foo = FILL(0xFF, int);

    return 0;
}

This would convert to the following assembly (64bit code):

.main
    ...
    subq    $16, %rsp       ! reserve space for rbp and foo
    movl    $._6, %eax      ! load address of ._6 (our static array)
    movl    (%rax), %eax    ! dereference rax and save value in eax
    movl    %eax, -4(%rbp)  ! save value of eax in `foo`
    ...

._6:
    .byte    -1
    .byte    -1
    .byte    -1
    .byte    0

If you're wondering why there is -1 and not 255 at the .byte directive, the number stands for 0b11111111 whereas -2 would stand for 0b11111110 and so on.

Comparsion to naive solution

The naive solution:

int foo = 0xFF << 16 | 0xFF << 8 | 0xFF

Compiles to the following assembly (64bit again):

.main:
    ...
    subq    $16, %rsp
    movl    $16777215, -4(%rbp)
    movl    -4(%rbp), %eax
    ...

The compiler optimizes the expression so it is a number which will be put into our variable foo. This is way better than loading an address and dereferencing it.

Conclusion

Use shifts, the compiler will optimize them anyway.