C语言中8个实用方法的代码优化
1,选择合适的算法和数据结构。
选择合适的数据结构非常重要。如果在一堆随机存储的数字中使用了大量的插入和删除指令,那么使用链表要快得多。数组与指针包密切相关。一般来说,指针灵活简洁,数组直观易懂。对于大多数编译器来说,使用指针比使用数组生成代码更短更有效。
2.使用尽可能小的数据类型
可以用character (char)定义的变量不应该用integer (int)变量定义;可以用整型变量定义的变量不要用long int,可以用浮点型变量也不要用。当然,定义了变量之后,不要超出变量的范围。如果赋值超出了变量的作用域,C编译器不会报错,但是程序运行结果是错误的,这样的错误很难发现。
3.降低操作强度。
a、查表(游戏程序员必修课)
一个聪明的游戏大虾,基本上不会在自己的主循环里做任何计算工作,肯定是先计算,然后在循环里查表。如果表很大,很难写,写一个init函数在循环之外临时生成表。
余数运算
位运算只需要一个指令周期就可以完成,C编译器的“%”运算大多是通过调用子程序来完成的,代码长,执行速度慢。一般只要求2n平方的余数,就可以用位运算法代替。
4.结构构件的布局
a、根据数据类型的长度
根据类型长度对结构成员进行排序,声明成员时将长类型放在短类型之前。编译器要求长数据类型存储在偶数地址边界。
b .将该结构填充为最长类型长度的整数倍。
将结构填充为最长类型长度的整数倍。这样,如果结构的第一个成员对齐,整个结构的所有成员自然也会对齐。
5、周期优化
一、充分分解小循环
要充分利用CPU的指令缓存,就要充分分解小循环,尤其是循环体本身很小的时候,可以提高性能。注意,许多编译器不能自动分解循环。
b .提取公共部分
对于一些不需要循环变量参与运算的任务,可以放在循环之外。这里的任务包括表达式、函数调用、指针操作、数组访问等。所有不需要执行很多次的操作都应该放在一起,放入init初始化程序中。
6.提高CPU的并行度。
a、使用并行代码
尽可能将长的依赖代码链分解成几个独立的代码链,这些代码链可以在流水线执行单元中并行执行。包括C++在内的很多高级语言都不会对生成的浮点表达式进行重新排序,因为这是一个相当复杂的过程。
避免对阅读和写作的不必要的依赖
当数据保存到内存时,存在读写依赖,即数据必须正确写入后才能再次读取。虽然AMD Athlon等CPU有硬件加速读写依赖的延迟,使得数据保存后在写入内存前先被读出,但如果避免读写依赖,将数据保存在内部寄存器中,速度会更快。
7.循环不变计算
可以把一些不需要循环变量参与运算的计算任务放到循环之外。现在很多编译器还是可以自己做的,但是不敢把中间用到变量的公式移动,所以很多情况下你得自己做。对于那些在循环中调用的函数,所有不需要多次执行的操作都放在一个init函数中,在循环之前调用。另外,尽量减少喂食次数,不需要的时候尽量不要给它传参数,需要循环变量的时候就让它自己建立一个静态循环变量来累加,这样会更快。
8、使用递归
与LISP等语言不同,C语言从一开始就喜欢使用重复的代码循环,很多C程序员坚决不使用递归,除非算法需要。
其实C编译器对优化递归调用一点都不反感。相反,他们非常喜欢这样做。只有当递归函数需要传递大量参数时,才应该使用循环代码,这可能会导致瓶颈。在其他时候,递归更好。