續(xù)接上篇 C語(yǔ)言基礎(chǔ)及指針①
在上一篇中 , 我們了解了C語(yǔ)言的基本語(yǔ)法 奴紧, 以及簡(jiǎn)單指針 , 也知道 晶丘, 指針是C語(yǔ)言的核心 黍氮, 那么我們今天就來(lái)簡(jiǎn)單剖析一下指針 , 了解他是怎么的神奇 浅浮。
今天是七夕 沫浆, 祝各位情人節(jié)快樂(lè) 。
指針的基本寫(xiě)法是int i = 10 ; int *p = &i ;
滚秩, 由此我們可以看出 专执, 指針和變量類似 , 其實(shí) 郁油, 指針也是變量 本股, 我們printf("%#x",p)
, 輸出的就是i的地址值 桐腌, p就是一個(gè)變量 拄显, 只是這個(gè)變量不普通 , 他可以通過(guò)他里面地址 案站, 操作這個(gè)地址里面的內(nèi)容 躬审, 這就是其強(qiáng)大之處 。那么他在內(nèi)存中是怎樣的呢 ? 下面我們來(lái)看看 盒件。
由圖上我們可知 , 指針變量就是用來(lái)操作內(nèi)存空間的 舱禽, 當(dāng)然也可以作為變量存儲(chǔ) 炒刁, 例如int *p = 100 ; printf("指針變量的值:%d\n",p)
這樣指針變量p就會(huì)輸出100 。
既然我們的指針也是變量 誊稚, 那么也是可以進(jìn)行運(yùn)算的 翔始, 下面我們就來(lái)看看 , 指針是怎么樣進(jìn)行運(yùn)算的 里伯。我們以一個(gè)數(shù)組輸出為例 城瞎, 來(lái)驗(yàn)證指針變量的運(yùn)算 , 如下:
void main() {
int arr[] = { 89,20,13,45,68 };
// 數(shù)組地址 疾瓮, 默認(rèn)是首個(gè)元素的內(nèi)存地址
printf("輸出數(shù)組arr地址:%#x\n", &arr);
printf("這樣也可以獲取到數(shù)組的地址:%#x\n", arr);
printf("第一個(gè)元素的地址: %#x\n", &arr[0]);
int* p = &arr;
// 以普通的方式進(jìn)行數(shù)組輸出
int i = 0;
for (; i < 5; i++)
{
printf("數(shù)組元素:%d\n", arr[i]);
}
printf("\n");
// 以指針運(yùn)算的方式進(jìn)行數(shù)組輸出
int j = 0;
for (; j < 5; j++)
{
printf("數(shù)組元素的值 : %d\n", *p);
p++;
}
printf("\n");
getchar();
}
從上述代碼我們可以看出 脖镀, 我們通過(guò)變量指針p進(jìn)行p++
操作 , 來(lái)獲取到數(shù)組中的值 狼电, 這樣操作的可能是 蜒灰, 因?yàn)閿?shù)組存儲(chǔ)數(shù)據(jù)的內(nèi)存空間是連續(xù)的 , 可以可以通過(guò)同類型的指針 肩碟, 進(jìn)行指針運(yùn)算來(lái)進(jìn)行內(nèi)存操作 强窖, 值得注意的是 , 指針類型必須和數(shù)組類型一致 削祈,才能進(jìn)行內(nèi)存操作 翅溺。由此 , 我們可以得出指針為什么需要類型的答案了:
指針是存儲(chǔ)的地址是開(kāi)始讀取的位置 髓抑, 類型是讀取的長(zhǎng)度 咙崎, 操作類型必須一致 。
下面我們來(lái)做一個(gè)實(shí)驗(yàn) 启昧, 如果使用不同類型的指針來(lái)讀取數(shù)組 叙凡, 這樣操作會(huì)出現(xiàn)什么情況 , 我們將上述代碼的int *p = @arr ;
更改為float *p = &arr;
會(huì)出現(xiàn)什么情況呢 ? 結(jié)果如下:
數(shù)組元素的值 : 0
數(shù)組元素的值 : 0
數(shù)組元素的值 : 0
數(shù)組元素的值 : 0
數(shù)組元素的值 : 0
我們使用float
類型的指針 密末, 去操作int類型的數(shù)組 握爷, 就完全取不到值了 。為什么會(huì)這樣呢 严里? 我們一探究竟 新啼, 打斷點(diǎn)去查看內(nèi)存的 , 我們輸出一下指針變量的值 刹碾, 然后對(duì)照數(shù)組變量的地址燥撞,如下:
指針變量存儲(chǔ)的值:0x101fdac -- 取值:0
數(shù)組元素:89 == 數(shù)組元素地址:0x101fdac
數(shù)組元素:20 == 數(shù)組元素地址:0x101fdb0
數(shù)組元素:13 == 數(shù)組元素地址:0x101fdb4
數(shù)組元素:45 == 數(shù)組元素地址:0x101fdb8
數(shù)組元素:68 == 數(shù)組元素地址:0x101fdbc
數(shù)組元素的值 : 0 == 指針存儲(chǔ)的地址:0x37064000
數(shù)組元素的值 : 0 == 指針存儲(chǔ)的地址:0x36e40000
數(shù)組元素的值 : 0 == 指針存儲(chǔ)的地址:0x36da0000
數(shù)組元素的值 : 0 == 指針存儲(chǔ)的地址:0x36f68000
數(shù)組元素的值 : 0 == 指針存儲(chǔ)的地址:0x37010000
我們可以看到 , 幾乎完全不一致了 , 地址都不相同了 物舒, 我有一個(gè)疑惑 色洞, 在第一次打印float指針變量值的時(shí)候 , 存儲(chǔ)的是數(shù)組第一個(gè)變量的內(nèi)存地址 冠胯, 但是在循環(huán)遍歷的時(shí)候 火诸, 卻不一樣了 , 目前不知道是什么原因?qū)е碌?荠察, 有知道的希望告知一下 置蜀。上述輸出完整程序:
以上問(wèn)題有一個(gè)答案了 , 雖然float和int類型都是四字節(jié)的 悉盆, 但是int 和 float的存儲(chǔ)方式不一樣 盯荤, 所有指針運(yùn)算會(huì)出現(xiàn)不一樣 。
void main() {
int arr[] = { 89,20,13,45,68 };
// 數(shù)組地址 焕盟, 默認(rèn)是首個(gè)元素的內(nèi)存地址
printf("輸出數(shù)組arr地址:%#x\n", &arr);
printf("這樣也可以獲取到數(shù)組的地址:%#x\n", arr);
printf("第一個(gè)元素的地址: %#x\n", &arr[0]);
//int* p = &arr;
float *p = &arr;
printf("指針變量存儲(chǔ)的值:%#x -- 取值:%f\n", p,*p);
int i = 0;
for (; i < 5; i++)
{
printf("數(shù)組元素:%d == 數(shù)組元素地址:%#x\n", arr[i],&arr[i]);
}
printf("\n");
int j = 0;
for (; j < 5; j++)
{
printf("數(shù)組元素的值 : %f == 指針存儲(chǔ)的地址:%#x\n", *p,p);
p++;
}
printf("\n");
getchar();
}
這次我們分析了指針在內(nèi)存中的情況 秋秤, 以及指針變量的簡(jiǎn)單運(yùn)算 , 下次我們來(lái)聊聊 脚翘, 指針在方法中的運(yùn)用 航缀, 以及二級(jí)指針 。
Android程序員學(xué)C系列:
C語(yǔ)言基礎(chǔ)及指針①
C語(yǔ)言基礎(chǔ)及指針②之指針內(nèi)存分析
C語(yǔ)言基礎(chǔ)及指針③函數(shù)與二級(jí)指針
C語(yǔ)言基礎(chǔ)及指針④函數(shù)指針
C語(yǔ)言基礎(chǔ)及指針⑤動(dòng)態(tài)內(nèi)存分配
C語(yǔ)言基礎(chǔ)及指針⑥字符操作
C語(yǔ)言基礎(chǔ)及指針⑦結(jié)構(gòu)體與指針
C語(yǔ)言基礎(chǔ)及指針⑧文件IO
C語(yǔ)言基礎(chǔ)及指針⑨聯(lián)合體與枚舉
C語(yǔ)言基礎(chǔ)及指針⑩預(yù)編譯及jni.h分析