上一篇:无线网的几种标准 - 下一篇:Firefox和Thunderbird的设置页面
2005-03
01
版权声明:可以任意转载,但转载时必须标明原作者charlee、原始链接http://tech.idv2.com/2005/03/01/unsigned-number-optimization/以及本声明。
昨天在讨论文档中的某个函数的实现方法的问题,我提议把某个循环计数变量unsigned int改成int,以便使用负值来表示出错信息。结果被人指出,改成int会影响代码效率,因为对这个变量有如下的操作:a = (a+1)%64,如果a为unsigned型,那么编译器会自动进行优化,而对于int型则不会。后来验证了一下果然如此。
测试环境为cygwin+gcc3.2。测试程序如下:
1 int main()
2 {
3 int a;
4 unsigned int b;
5 a = 20;
6 b = 21;
7 a = (a + 1) % 64;
8 b = (b + 1) % 64;
9 return 0;
0 }
编译并查看汇编代码:
$ gcc test.c $ gdb a.exe # 调试执行 (gdb) b main # 在main函数处设置断点 (gdb) r # 运行 (gdb) disass # 反汇编
结果如下所示:
; a = 20 movl $0x14,0xfffffffc(%ebp) ; b = 21 movl $0x15,0xfffffff8(%ebp) ; a = a + 1 mov 0xfffffffc(%ebp),%edx inc %edx mov %edx,0xfffffff0(%ebp) ; a = a % 64 mov 0xfffffff0(%ebp),%eax mov %eax,0xffffffec(%ebp) cmpl $0x0,0xffffffec(%ebp) jns 0x4010e3 <main+67> addl $0x3f,0xffffffec(%ebp) mov 0xffffffec(%ebp),%eax ; << here is <main+67> sar $0x6,%eax mov %eax,0xfffffffc(%ebp) mov 0xfffffffc(%ebp),%eax shl $0x6,%eax mov 0xfffffff0(%ebp),%edx sub %eax,%edx mov %edx,%eax mov %eax,0xfffffffc(%ebp) ; a = a + 1 mov 0xfffffff8(%ebp),%eax inc %eax ; a = a % 64 and $0x3f,%eax mov %eax,0xfffffff8(%ebp)
可以看出,对于无符号型整数,编译器会自动把 % 64的运算转换成 and 0x3f,而对于符号整数则不会。因此,在进行位运算或者是对2的幂取模时,应当尽量使用无符号整数,或者是在运算之前进行强制类型转换。
添加评论
