Pointer - declaration - const
const 顧名思義就是不可被改變的意思。
const int a = 10;
也意味著 a 在消失之前就是 10 了。
結合指標應用可提升code的可讀性以及效率。
考慮以下code
int a = 10;
int * p1 = &a;
const int * p2 = &a;
int * const p3 = &a;
p1 應該是沒有什麼問題,我們來看 p2 如何解讀
我們考慮 const int, * 和 p2 . 這三個要素告訴我們 - p2 是個指向 const int 的指標。
也就是說*p2 的型態是 const int .
這也告訴我們 *p2 無法修改, *p2 = 30 是一個違法的語法,縱使 a 根本不是一個 const。
用擬人化的說法就是 - p2 以為他指向的物件是一個常數。
而這邊要提醒的是 - p2 本身並非常數,p2 本身可以被改變。
p3 方面,我們應該 int*, const , p3 這樣看。p3 是一個常數指標,指向int
這告訴我們 p3 無法被改變,但是 *p3 可以.
應用
最常使用到 point to const 的莫過於在使用 function 時傳遞參數了。例如說
void show(int * a, int size)
{
int i = 0;
for (i = 0; i < size; ++i)
printf("%d ", a[i]);
}
這個 function很清楚的他只是要印東西而已。邏輯上我們不應該去改變 a 的內容。 而 show "有權" 改變 a 的內容。
那我們考慮另外一個情況 - 假設 show 被包在一個 dll 或是某個 libs 裡面,我們使用其他人的 function,對使用者而言只可知道他的prototype 是 void show(int * a, int size)
那我們在使用時是否會擔心傳進去的東西會被改變?
而 const 的使用也有助於 complier 最佳化。
另外一個例子是 struct
typedef struct Buffer
{
int val[1024];
int size;
} Buffer;
int sumBuffer(Buffer buf)
{
int i = 0;
int sum = 0;
for (i = 0; i < buf.size; ++i)
sum += buf.val[i];
return sum;
}
Buffer是一個簡易的 buffer,size是目前使用了多少。
這段 code 用意是將 buffer內的值全部相加並回傳,乍看之下一點問題也沒有,也應該可以work。
然而最大的問題是效率。
sizeof(Buffer) 應該是一個相當大的數字,然後 C 是 call-by-value 的做法,因此會複製一個 buf 來操作。但是在這邊一點必要也沒有。
事實上我們只要將 function 修改為
int sumBuffer(const Buffer * buf)
{
int i = 0;
int sum = 0;
for (i = 0; i < buf->size; ++i)
sum += buf->val[i];
return sum;
}
這樣就可以就可提升效率。