在将整数写入十六进制字符串函数时,我注意到我有一个不必要的掩码和位移,但是当我删除它时,代码实际上变得更大(大约 8 倍)
char *i2s(int n){
static char buf[(sizeof(int)<<1)+1]={0};
int i=0;
while(i<(sizeof(int)<<1)+1){ /* mask the ith hex, shift it to lsb */
// buf[i++]='0'+(0xf&(n>>((sizeof(int)<<3)-i<<2))); /* less optimizable ??? */
buf[i++]='0'+(0xf&((n&(0xf<<((sizeof(int)<<3)-i<<2)))>>((sizeof(int)<<3)-i<<2)));
if(buf[i-1]>'9')buf[i-1]+=('A'-'0'-10); /* handle A-F */
}
for(i=0;buf[i++]=='0';)
/*find first non-zero*/;
return (char *)buf+i;
}
使用额外的位移位和掩码并用 编译gcc -S -O3
,循环展开并减少为:
movb $48, buf.1247
xorl %eax, %eax
movb $48, buf.1247+1
movb $48, buf.1247+2
movb $48, buf.1247+3
movb $48, buf.1247+4
movb $48, buf.1247+5
movb $48, buf.1247+6
movb $48, buf.1247+7
movb $48, buf.1247+8
.p2align 4,,7
.p2align 3
.L26:
movzbl buf.1247(%eax), %edx
addl $1, %eax
cmpb $48, %dl
je .L26
addl $buf.1247, %eax
ret
这就是我对 32 位 x86 的预期(应该是相似的,但 64 位的类似 movb 的操作数是其两倍);但是,如果没有看似多余的掩码和位移,gcc 似乎无法展开和优化它。
任何想法为什么会发生这种情况?我猜这与 gcc 对符号位(过度?)谨慎有关。(C 中没有 >>> 运算符,因此如果设置了符号位,则使用 1 与 0 对 MSB >> 填充进行位移)