我在各个地方遇到过以下RGB-to-int方法:
//r,g, and b are bytes
int c = r;
c = (C << 8) | g;
c = (c << 8) | b;
return c;
但说:
是否更有效率return (r << 16) | (g << 8) | r;
似乎第一种方式会导致大量不必要的存储/加载指令。是不是每个人都喜欢第一种方式而不是第二种方式?
答案 0 :(得分:1)
在第二个表达式中,你做了一个小错字:两次使用&#34; r&#34;,从不&#34; b&#34;。我想,你的意思是:
return (r << 16) | (g << 8) | b;
关于您的问题:结果非常依赖于您的计算机体系结构和编译器版本。我用clang CC,FreeBSD OS,-O3构建了两个版本。 源代码:
int rgb1(int r, int g, int b) {
int c = r;
c = (c << 8) | g;
c = (c << 8) | b;
return c;
}
int rgb2(int r, int g, int b) {
return (r << 16) | (g << 8) | b;
}
unsigned int rgb3(unsigned int r, unsigned int g, unsigned int b) {
return (r * 256*256) + (g * 256) + b;
}
汇编代码如下:
rgb1:
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %eax
sall $8, %eax
orl 12(%ebp), %eax
sall $8, %eax
orl 16(%ebp), %eax
popl %ebp
ret
.size rgb1, .-rgb1
.p2align 4,,15
.globl rgb2
.type rgb2, @function
rgb2:
pushl %ebp
movl %esp, %ebp
movl 12(%ebp), %eax
movl 8(%ebp), %edx
sall $8, %eax
orl 16(%ebp), %eax
popl %ebp
sall $16, %edx
orl %edx, %eax
ret
.size rgb2, .-rgb2
.p2align 4,,15
.globl rgb3
.type rgb3, @function
rgb3:
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %eax
sall $8, %eax
addl 12(%ebp), %eax
sall $8, %eax
addl 16(%ebp), %eax
popl %ebp
ret
如您所见,第一个功能是9个指令,第二个功能是10.因此,第一个功能似乎更有效率。但是,在现实生活中,它很大程度上取决于您的编译器行为。 例如,rgb3()使用了许多数学运算,但编译器将其优化为非常接近rgb1()的东西。