通常,资源在不同进程之间共享。假设您的程序占用更多资源,那么肯定会影响需要相同资源的其他进程的性能。因此,我们需要考虑资源(例如处理器的时间和主内存)来编写和优化程序。
以下是一些优化技术
- 循环优化
- 展开小循环:大多数情况下,编译器会自动执行此操作,但这是编写优化代码的好习惯。使用此方法进行矩阵更新非常有优势。
程序1:
#include
int main(void) { int fact[5]; fact[0] = 1; // Overhead of managing a counter // just for 4 iterations // is not a good idea for (int i = 1; i < 5; ++i) { fact[i] = fact[i - 1] * i; } return 0; } 程式2:
#include
int main(void) { int fact[5] = { 1, 1, 2, 6, 24 }; // Here the same work is done // without counter overhead return 0; } - 避免循环计算:我们应避免任何值或多或少恒定的计算。内循环应尽可能少地进行计算。
程序1:#include
int main(void) { int arr[1000]; int a = 1, b = 5, c = 25, d = 7; // Calculating a constant expression // for each iteration is not good. for (int i = 0; i < 1000; ++i) { arr[i] = (((c % d) * a / b) % d) * i; } return 0; } 程式2:
#include
int main(void) { int arr[1000]; int a = 1, b = 5, c = 25, d = 7; // pre calculating the constant expression int temp = (((c % d) * a / b) % d); for (int i = 0; i < 1000; ++i) { arr[i] = temp * i; } return 0; } - 避免在循环中使用指针取消引用:指针取消引用会在内存中造成很多麻烦。因此最好将其分配给某个临时变量,然后在循环中使用该临时变量。
程序1:#include
int main(void) { int a = 0; int* iptr = &a; // Dereferencing pointer inside loop // is costly for (int i = 1; i < 11; ++i) { *iptr = *iptr + i; } printf("Value of a : %d", a); return 0; } 输出:Value of a : 55
程式2:
#include
int main(void) { int a = 0; int* iptr = &a; // Dereferencing pointer outside loop // and saving its value in a temp variable int temp = *iptr; for (int i = 1; i < 11; ++i) { // performing calculations on temp variable temp = temp + i; } // Updating pointer using final value of temp *iptr = temp; printf("Value of a : %d", a); return 0; } 输出:Value of a : 55
- 将寄存器变量用作内部循环的计数器:与存储在内存中的变量相比,访问存储在寄存器中的变量的速度要快得多。
程序:#include
int main(void) { register int i = 0; register int j = 0; int n = 5; // using register variables // as counters make the loop faster for (i = 0; i < n; ++i) { for (j = 0; j <= i; ++j) { printf("* "); } printf("\n"); } return 0; } 输出:* * * * * * * * * * * * * * *
- 展开小循环:大多数情况下,编译器会自动执行此操作,但这是编写优化代码的好习惯。使用此方法进行矩阵更新非常有优势。
- 快速数学
- 避免不必要的整数除法:除法运算很慢,因此我们应尽量减少除法运算。
程序:#include
int main(void) { int a = 100, b = 2, c = 5; // int d=a/b/c; two division operators int d = a / (b * c); // single division operator return 0; } - 乘以2的幂进行除法:将左移(<<)用于乘法,将右移(>>)用于除法。位运算将比乘法和除法运算快得多。对于简单运算,编译器可能会自动优化代码,但在表达式复杂的情况下,始终建议使用位运算。
例子 :Multiply by 6 : a= a<<1 + a<<2; Multiply by 7 : a= a<<3 - a; Divide by 8 : a= a>>3; // division by power of 2
- 简化表达式:有时我们可以通过简化表达式来减少某些操作。
例子 :a*b + a*b*c + a*b*c*d ---> (a*b)*(1 + c*(1 + d)) L.H.S can be Simplified to R.H.S L.H.S : 6 multiplications and 2 additions R.H.S : 3 multiplications and 2 additions
- 避免不必要的整数除法:除法运算很慢,因此我们应尽量减少除法运算。
- 使用switch语句进行优化
编译器以不同的方式转换switch语句。如果案例标签是小的连续整数值,则它将创建一个跳转表。这非常快,并且也不取决于案例标签的数量。如果案例标签较长且不连续,则它将创建比较树,即if … else语句。因此,在这种情况下,我们应该将最频繁使用的标签放在最前面,而最不频繁使用的标签应该放在最后。有时我们会在所有情况下看到很多重复的代码,只有一两个语句
例子 :
switch(expression) { case a: ........ ........ break; case b: ........ ........ break; case c: common statements; different statements; common statements; break; case d: common statements; different statements; common statements; break; ' case e: common statements; different statements; common statements; break; case f: common statements; different statements; common statements; break; default: break; }
我们可以将所有情况汇总在一起,并且只能编写一次公共语句,而在相关情况下使用另一个开关可以编写不同的语句。在这里,我们将案例c,d,e,f放在一起并编写公共语句,然后我们可以使用另一个开关在案例c,d,e,f中编写不同的语句。然后,在此切换之后,我们可以再次编写公共语句。
switch(expression) { case a: ........ ........ break; case b: ........ ........ break; case c: case d: case e: case f: common statements; switch(expression); { case c: different statements; break; case d: different statements; break; case e: different statements; break; case f: different statements; break; } /*End of switch*/ common statements; break; default: break; }/*End of switch*/
- 首选int而不是char或short
我们应该始终首选int而不是char,因为C用整数执行char的所有操作。在将char传递给函数或算术运算之类的所有操作中,第一个char将被转换为整数,并且在编译该操作后,将其再次转换为char 。对于单个字符,这可能不会影响效率,但是假设同一操作在一个循环中执行了100次,则可能会降低程序的效率。 - 优先于前增量/减量,而不是后增量/减量
在递增之前,它首先递增值,然后将值复制到变量位置,但是在递增之后,首先将值复制到临时变量,将其递增,然后将值复制到变量位置。如果循环后增加1000次,则会降低效率。 - 表达顺序评价
-
A || B
在这里,首先将对A进行评估,如果它为true,则不需要评估表达式B。因此,我们应该更喜欢在A处拥有一个大多数情况下都评估为true的表达式。
-
A && B
在这里,首先将对A进行评估,如果它为假,则无需评估表达式B。因此,我们应该更喜欢在A处拥有一个大多数情况下都为假的表达式。
-
想要从精选的最佳视频中学习和练习问题,请查看《基础知识到高级C的C基础课程》。