首页 > 编程知识 正文

c语言从入门到精通,c语言进阶 c和指针

时间:2023-05-04 05:48:55 阅读:153521 作者:4207

在学习资料满天飞的大环境下,由于知识非常零散,系统化的知识很少,很多人每天都为了感动自己而学习,但最终收效甚微,放弃了学习。 我的任务是过滤大量的垃圾信息,将知识系统化,快速到达问题的本质,让大家摆脱大海捞针的痛苦。

文章目录1定义2应用场景3注意事项4作用机制4.1理论4.2实践4.2.1不使用unlikely或unlikely选项使用4.2.2likely选项使用4.2.3unlikely选项

1定义1#definelikely(x ) __builtin_expect (! (x ),1 )2 #define unlikely(x ) x ) __builtin_expect (! (x ),0 ) )。

__builtin_expect是编译器中的内置函数,原型为long__builtin_expect(longexp,long c )。 此函数不更改exp的值,但可以优化if-else分支或if分支结构。 likely表示if分支概率发生,unlikely表示if分支概率不发生。

Tips: 用c语言处理逻辑表达式的技巧。 由于c语言没有布尔变量,因此布尔值将由格式替换。 0为假,0以外为真。 当x为0时! (x )是1, (x )是0, 运算没有什么意义。但是,如果x不是0 (例如100 ), (x )是0, ) x )为1,由此可以获得将除0以外的值(例如100 )全部映射为1的效果。

分析表明,unlikely的定义实际上可以不用! 运算符的。

2 APP场景通常,对于要求代码执行效率较高的if-else或if分支,必须使用likely或unlikely优化选项。

3注意事项likely和unlikely的概率判断一定要正确,不要反过来写。 否则,不仅不会提高执行效率,反而会起到相反的效果。 选择表达式时,请选择编译器在编译时无法推测真伪的表达式。 否则,优化将不起作用。 编译时必须至少使用-O2选项。 如果不使用,优化将不起作用。 4作用机制4.1为什么使用理论likely或unlikely会产生优化效果,以提高代码的执行效率呢?

主要作用机制有以下两点。

在编译时生成汇编代码时,gcc编译器会在编译选项的引导下调整代码在if分支中的位置。 如果由likely修饰,则向前调整;如果由unlikely修饰,则向后调整。 通过放置在前面的代码中,可以节约跳转命令所需的时间开销,提高效率。 现代CPU具有ICache和流水线机制,在执行当前指令时,ICache会预读后续指令以提高执行效率。 但是,作为条件分支的结果,跳转到其他指令时,预取的下一个指令(根据CPU的不同,为4级流水,也就是4个指令)会被浪费,导致流水线效率降低。 如果使用likely和unlikely指示编译器始终将高概率执行的代码放在前列,则预取值的命中率将大幅提高,从而提高效率。 4.2实践接下来用小栗子感受一下likely和unlikely的行动吧。

期间使用的工具是gcc和objdump。 相关命令如下

#请注意,编译并生成a.out,然后使用-O2选项。 否则,gcc -O2 test.c#将不会生效。 从生成的a.out生成的反汇编代码objdump-CsA.out objdump.txt tips 3360 objdump命令是显示目标文件或可执行目标文件的配置的gcc

(1) d )反汇编对象文件中包含的可执行指令。

)2) s )混合显示源代码和汇编代码。 假设在编译目标文件时添加-g。 否则就相当于-d。

)3) c )一般用于相对于c语言更友好地显示符号名称。

4.2.1 % 20 % E4 % b8 % 8d % E4 % BD % BF % E7 % 94 % A8 likely % E6 % 88 % e9 % 80 % e9 % a1 % B9 % 20 % 25 % 20a1% B9 % 20a1% 20a9% 209 % 200 % 7b % 200 % 2020 with % 20 the % 20 value % 20 that % 20g cc % 20 can % 27t % 20 optimize % 20 % 2a % 2f % 207 % 208 if % 20 % 28i % % 9c % aa % E4 % BD % BF % E7 % 94 % A8 likely % E6 % 201 % 2045 % 2008048320 % 20 main : % 2046 % 2080483203360 % 2055 % 20 0 and % 20 % 240 xffffff0% 2c % 25 esp % 2049 % 208048326: % 2083 % 2010 EC % 20 sub % 20 % 240 X10 % 25 esp

8b 45 0c mov 0xc(%ebp),%eax 51 804832c: 8b 40 04 mov 0x4(%eax),%eax 52 804832f: 89 04 24 mov %eax,(%esp) 53 8048332: e8 d9 ff ff ff call 8048310 <atoi@plt> 54 8048337: c9 leave 55 8048338: 8d 50 ff lea -0x1(%eax),%edx !注意到if分支内容在前 56 804833b: 85 c0 test %eax,%eax 57 804833d: 8d 48 01 lea 0x1(%eax),%ecx !注意到else分支内容在后 58 8048340: 0f 4e d1 cmovle %ecx,%edx 59 8048343: 89 d0 mov %edx,%eax 60 8048345: c3 ret 4.2.2 使用likely选项 1 #define likely(x) __builtin_expect(!!(x), 1) 2 #define unlikely(x) __builtin_expect(!!(x), 0) 3 4 int main(int argc, char *argv[]) 5 { 6 int i = atoi(argv[1]); /* init i with the value that GCC can't optimize */ 7 8 if (likely(i > 0)){ 9 i--; 10 }else{ 11 i++; 12 } 13 14 return i; 15 } ! 使用likely后的反汇编代码 45 08048320 <main>: 46 8048320: 55 push %ebp 47 8048321: 89 e5 mov %esp,%ebp 48 8048323: 83 e4 f0 and $0xfffffff0,%esp 49 8048326: 83 ec 10 sub $0x10,%esp 50 8048329: 8b 45 0c mov 0xc(%ebp),%eax 51 804832c: 8b 40 04 mov 0x4(%eax),%eax 52 804832f: 89 04 24 mov %eax,(%esp) 53 8048332: e8 d9 ff ff ff call 8048310 <atoi@plt> 54 8048337: 85 c0 test %eax,%eax 55 8048339: 7e 05 jle 8048340 <main+0x20> 56 804833b: 83 e8 01 sub $0x1,%eax !注意到if分支内容在前 57 804833e: c9 leave 58 804833f: c3 ret 59 8048340: 83 c0 01 add $0x1,%eax !注意到else分支内容在后 60 8048343: c9 leave 61 8048344: c3 ret 4.2.3 使用unlikely选项 1 #define likely(x) __builtin_expect(!!(x), 1) 2 #define unlikely(x) __builtin_expect(!!(x), 0) 3 4 int main(int argc, char *argv[]) 5 { 6 int i = atoi(argv[1]); /* init i with the value that GCC can't optimize */ 7 8 if (unlikely(i > 0)){ 9 i--; 10 }else{ 11 i++; 12 13 14 return i; 15 } ! 使用unlikely选项的反汇编结果 45 08048320 <main>: 46 8048320: 55 push %ebp 47 8048321: 89 e5 mov %esp,%ebp 48 8048323: 83 e4 f0 and $0xfffffff0,%esp 49 8048326: 83 ec 10 sub $0x10,%esp 50 8048329: 8b 45 0c mov 0xc(%ebp),%eax 51 804832c: 8b 40 04 mov 0x4(%eax),%eax 52 804832f: 89 04 24 mov %eax,(%esp) 53 8048332: e8 d9 ff ff ff call 8048310 <atoi@plt> 54 8048337: 85 c0 test %eax,%eax 55 8048339: 7f 05 jg 8048340 <main+0x20> 56 804833b: 83 c0 01 add $0x1,%eax !注意到else分支内容被提前了 57 804833e: c9 leave 58 804833f: c3 ret 59 8048340: 83 e8 01 sub $0x1,%eax !注意到if分支内容被后移了 60 8048343: c9 leave 61 8048344: c3 ret

<完>

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。