進階指標-指標的使用@ Bryan的C語言筆記 - 隨意窩
文章推薦指數: 80 %
我們在上一篇提到了指標運算子. 其中int *ptr 與*ptr的意義是不同的. int *ptr 是對於指標變數的定義,稱之為指向整數空間的指標. 而*ptr 我們稱之為反參照運算子, ...
Bryan的C語言筆記程式語言與生活語言一樣多碰就會少碰會忘可當工具,可當興趣日誌相簿影音好友名片
201506230222進階指標-指標的使用?C這次我們要提到較深入的指標觀念了
如果要重新溫習一下簡易的指標概念
傳送門:指標入門-淺談指標的藝術
就讓我們來繼續了解這個雖然困難但非常好用的指標運算吧
我們在上一篇提到了指標運算子
其中int*ptr與*ptr的意義是不同的
int*ptr是對於指標變數的定義,稱之為指向整數空間的指標
而*ptr我們稱之為反參照運算子,表示傳ptr中位址的內容值
而接著我們要再介紹一個運算子
稱為取址運算元(addressoperator),表示法為"&",使用取址運算元可以回傳該空間的位址,例如:
inta=5;//宣告一個變數a,初始值為5
int*value=&a;宣告一個可存放位址的變數value,並將變數a的位址值給value
intb=*value;//將a位址的內容值傳給b
print("b=%d",b);//這樣print出b的值,即為a的內容值,b=5
由上面的例子我們可以知道,&a只是將變數a空間的位址取出來,我們並不知道a的內容值,但我們知道a的記憶體位址資訊
而最後一行的b,由於value已經知道a的記憶體位址了,因此使用反參照運算子就可以將a的內容值傳出來給b,這樣b的結果就是5了
接下來就要來討論
char*value;
int*value;
double*value;
這幾個的差異了
因此我們先從"型態的記憶體大小"提起
我們都知道每個型態的記憶體空間都有特定的大小
型態
記憶體大小(位元/位元組)
char
8/1
int
32/4
unsignedint
32/4
short
16/2
float
32/4
double
64/8
當你不知道的時候,求證的方法只有一種:使用sizeof()函式
sizeof()並不是只有使用在陣列上,他一樣可以使用在型態上
例如
sizeof(int)、sizeof(char)、sizeof(double)...etc
而這樣顯示出來的數值,都是以“位元組”來表示
也就是說你執行printf("%d",sizeof(int));這段程式碼的話
你得到的值就是4,因為一個int型態的空間即為4bytes
而一個位元組,就是8bit,這樣就可以換算出int型態為4*8=32bits
你可能會問說:請問一下可不可以這樣做
printf("%d",sizeof(int*));
printf("%d",sizeof(char*));
printf("%d",sizeof(double*));
.
.
.
正確答案是:YES!
你可以去實驗看看
執行上述程式碼的結果
你會得到一個驚人的結果
你會發現這三條程式碼做出來的數值都是“4”
這又是為什麼呢?
因為,int*是一個存放位址的型態宣告,因此以現今電腦的定址大小
皆為32bits定址,也就是每一個記憶體空間,都是用一個32bits的數值來表示
只是每個空間的大小,就要看你前面的型態而定
char就是一個1byte的空間
double就是一個8byte的空間
.
.
(以此類推)
接下來,我們討論一個觀念
我們稱之為call-by-value(傳值呼叫)與call-by-reference(傳址呼叫)
這種概念常用於函式的呼叫
我們來看下面的簡單的範例:
//call-by-value
intmain()
{
inta=5;
intb=3;
intc;
c=intADD(a,b);
printf("a+b=%d",c);
return0;
}
intintADD(intx,inty)
{
intz;
z=x+y;
returnz;
}
很明顯的我們可以知道結果為a+b=8
因為我們知道我們將值傳到函式內做運算,並且直接將值return回變數上,這樣就可以直接計算出我們的結果
那如果程式碼修改成下面這種情形呢?
//call-by-reference(error)
intmain()
{
inta=5;
intb=3;
intc;
intADD(a,b,c);
printf("a+b=%d",c);
return0;
}
voidintADD(intx,inty,intz)
{
z=x+y;
}
這樣的結果會與上面相同嗎?
結果是不會的,函式通常宣告結束後,後方所接的變數都是以“傳入”為導向
這樣對於前面的call-by-value的方式是行不通的,也就是說,雖然z改變了它本身的值
但是c卻一丁點都沒有被影響
所以如果真的要這樣寫
我們會修改成
//call-by-reference(correct)
intmain()
{
inta=5;
intb=3;
intc;
intADD(&a,&b,&c);//傳入a,b,c的位址
printf("a+b=%d",c);
return0;
}
voidintADD(int*x,int*y,int*z)
{
*z=*x+*y;//改變了位址的內容值,相對的傳回去的內容值也會改變
}
這樣的話我們會將c的位址傳入,並且改變z的內容值,最後傳回去時c就會相對改變了
而我們把上述的兩個方法用一句白話文來做整理
第二種方法,就是利用call-by-reference來模擬出call-by-value的效果
由於C語言中並沒有直接定義call-by-reference的用法(C++中就有定義)
因此我們只能夠模擬出相同的效果而已
說了這麼多,想必也對call-by-value/call-by-reference有一些概念了
我們最後就來說說陣列與指標的使用方式吧
陣列的觀念,如果有疑惑的可以在下方留言或是在網路上尋找
參考網址:陣列
陣列經常使用在繪圖處理、查表、字串的運算上
其中以字串的運算最為常見
我們就用簡單的程式碼跟大家討論指標如何運用於字串處理
#include
延伸文章資訊
- 1C語言: 超好懂的指標,初學者請進~ - 寫點科普Kopuchat
指標向來是初學者多麼痛的領悟,決定來寫一篇指標的教學解救初學者 ... 今天的指標與指標變數教學就到這邊,下一篇會來介紹指標與陣列的相互應用。
- 2指標(電腦科學) - 維基百科,自由的百科全書
使用指標能夠簡化許多資料結構的實作,例如在走訪字串,查取表格,控制表格及樹狀結構上。對指標進行複製,之後再解參照指標以取出資料,無論在時間或空間上,都比直接複製 ...
- 31 你所不知道的C 語言: 指標篇☢️ - HackMD
- 4指標
int *p; //宣告p是指向int的指標,英文說成p is a pointer to int ... *p = 0; //透過p將a的值被設定為0. p = &c; //指標p現在指向c. ...
- 5第5章、陣列和指標 - C/C++
但是有三種應用場合,使用指標仍然是必要的。第一是字串(string)的宣告;第二是動態記憶體配置(dynamic memory allocation);第三是函式的 ...