本篇給您列舉10個C語言的優化案例,并展示未優化前和優化後的代碼。這裡我們将用到一個數組排序的例子來示範這些優化技術。
- 循環展開 (Loop Unrolling)
循環展開是一種将循環體重複執行多次,進而減少循環開銷的優化技術。下面是一個未優化前的例子:
void unrolled_loop(int arr[], int n) {
for (int i = 0; i < n; i++) {
arr[i] = i + 1;
}
}
優化後的代碼:
void unrolled_loop(int arr[], int n) {
int i = 0;
for (; i < n - 4; i += 4) {
arr[i] = i + 1;
arr[i + 1] = i + 2;
arr[i + 2] = i + 3;
arr[i + 3] = i + 4;
}
for (; i < n; i++) {
arr[i] = i + 1;
}
}
- 資料對齊 (Data Alignment)
資料對齊是一種将資料存儲在記憶體中的位址按照一定的規則對齊,進而提高通路速度的優化技術。下面是一個未優化前的例子:
struct data {
int x;
int y;
};
void data_alignment(struct data* arr, int n) {
for (int i = 0; i < n; i++) {
arr[i].x = i;
arr[i].y = i * 2;
}
}
優化後的代碼:
struct data {
int x;
int y;
} __attribute__((aligned(16)));
void data_alignment(struct data* arr, int n) {
for (int i = 0; i < n; i++) {
arr[i].x = i;
arr[i].y = i * 2;
}
}
- 寄存器變量 (Register Variables)
寄存器變量是一種将變量存儲在寄存器中,進而提高通路速度的優化技術。下面是一個未優化前的例子:
void register_variable(int arr[], int n) {
int sum = 0;
for (int i = 0; i < n; i++) {
sum += arr[i];
}
printf("Sum: %d\n", sum);
}
優化後的代碼:
void register_variable(register int arr[], register int n) {
register int sum = 0;
for (register int i = 0; i < n; i++) {
sum += arr[i];
}
printf("Sum: %d\n", sum);
}
- 常量傳遞 (Passing Constants)
常量傳遞是一種将常量作為參數傳遞給函數,進而提高通路速度的優化技術。下面是一個未優化前的例子:
void constant_parameter(int n) {
int sum = 0;
for (int i = 1; i <= n; i++) {
sum += i;
}
printf("Sum: %d\n", sum);
}
優化後的代碼:
void constant_parameter(const int n) {
int sum = 0;
for (int i = 1; i <= n; i++) {
sum += i;
}
printf("Sum: %d\n", sum);
}
- 預計算 (Precomputation)
預計算是一種在程式執行前提前計算出結果,進而減少運作時間的優化技術。下面是一個未優化前的例子:
void precomputation(int arr[], int n) {
int sum = 0;
for (int i = 0; i < n; i++) {
sum += arr[i];
}
double avg = sum / n;
printf("Average: %.2lf\n", avg);
}
優化後的代碼:
void precomputation(int arr[], int n) {
int sum = 0;
for (int i = 0; i < n; i++) {
sum += arr[i];
}
double avg = (double)sum / (double)n;
printf("Average: %.2lf\n", avg);
}
- 去除函數調用 (Eliminating Function Calls)
去除函數調用是一種将函數調用替換為函數體内的代碼,進而減少函數調用開銷的優化技術。下面是一個未優化前的例子:
int max(int a, int b) {
return a > b ? a : b;
}
void eliminating_function_calls(int arr[], int n) {
int max_val = arr[0];
for (int i = 1; i < n; i++) {
max_val = max(max_val, arr[i]);
}
printf("Max value: %d\n", max_val);
}
優化後的代碼:
void eliminating_function_calls(int arr[], int n) {
int max_val = arr[0];
for (int i = 1; i < n; i++) {
if (arr[i] > max_val) {
max_val = arr[i];
}
}
printf("Max value: %d\n", max_val);
}
- 短路求值 (Short-Circuit Evaluation)
使用短路求值可以減少不必要的運算,提高程式的執行效率。例如,在進行邏輯運算時,如果前面的表達式已經能夠确定整個表達式的值,那麼後面的表達式就不需要再進行運算了。下面是一個未優化前的例子:
bool short_circuit_evaluation(int a, int b) {
if (a != 0 && b / a > 1) {
return true;
}
return false;
}
優化後的代碼:
bool short_circuit_evaluation(int a, int b) {
if (a && b > a) {
return true;
}
return false;
}
在這個優化後的代碼中,當 a 為 0 時,第一個表達式傳回 false,後面的表達式不再進行運算,進而減少了不必要的運算。
- 資料結構選擇 (Choosing Data Structures)
選擇合适的資料結構可以提高程式的執行效率。例如,在需要快速查找資料時,可以使用散清單而不是數組。下面是一個未優化前的例子:
struct student {
char name[20];
int id;
float gpa;
};
void choosing_data_structures(struct student arr[], int n, int id) {
for (int i = 0; i < n; i++) {
if (arr[i].id == id) {
printf("Name: %s, GPA: %.2f\n", arr[i].name, arr[i].gpa);
return;
}
}
printf("Student not found\n");
}
優化後的代碼:
#include <stdbool.h>
#include <string.h>
#define TABLE_SIZE 1000
struct student {
char name[20];
int id;
float gpa;
};
struct hash_table {
int key;
struct student data;
};
void choosing_data_structures(struct student arr[], int n, int id) {
struct hash_table table[TABLE_SIZE];
memset(table, 0, sizeof(table));
for (int i = 0; i < n; i++) {
int key = arr[i].id % TABLE_SIZE;
while (table[key].key != 0) {
key = (key + 1) % TABLE_SIZE;
}
table[key].key = arr[i].id;
table[key].data = arr[i];
}
int key = id % TABLE_SIZE;
while (table[key].key != 0) {
if (table[key].key == id) {
printf("Name: %s, GPA: %.2f\n", table[key].data.name, table[key].data.gpa);
return;
}
key = (key + 1) % TABLE_SIZE;
}
printf("Student not found\n");
}
- 位運算 (Bitwise Operations)
使用位運算可以提高程式的執行效率,例如在進行整數倍數檢查時,可以使用位運算代替模運算。下面是一個未優化前的例子:
bool is_multiple_of_4(int n) {
return n % 4 == 0;
}
優化後的代碼:
bool is_multiple_of_4(int n) {
return (n & 3) == 0;
}
- 并行化 (Parallelization)
使用并行化可以利用多核處理器的優勢,提高程式的執行效率。下面是一個未優化前的例子:
void parallelization(float a[], float b[], float c[], int n) {
for (int i = 0; i < n; i++) {
c[i] = a[i] + b[i];
}
}
優化後的代碼:
#include <omp.h>
void parallelization(float a[], float b[], float c[], int n) {
#pragma omp parallel for
for (int i = 0; i < n; i++) {
c[i] = a[i] + b[i];
}
}