續接上篇 [C語言基礎及指針①](http://www.jianshu.com/p/4701cd1e1914)
在上一篇中 , 我們了解了C語言的基本語法 , 以及簡單指針 , 也知道 , 指針是C語言的核心 , 那么我們今天就來簡單剖析一下指針 , 了解他是怎么的神奇 。
> 今天是七夕 , 祝各位情人節快樂 。
指針的基本寫法是`int i = 10 ; int *p = &i ;` , 由此我們可以看出 , 指針和變量類似 , 其實 , 指針也是變量 , 我們`printf("%#x",p)` , 輸出的就是i的地址值 , p就是一個變量 , 只是這個變量不普通 , 他可以通過他里面地址 , 操作這個地址里面的內容 , 這就是其強大之處 。那么他在內存中是怎樣的呢 ? 下面我們來看看 。

由圖上我們可知 , 指針變量就是用來操作內存空間的 , 當然也可以作為變量存儲 , 例如`int *p = 100 ; printf("指針變量的值:%d\n",p)`這樣指針變量p就會輸出100 。
既然我們的指針也是變量 , 那么也是可以進行運算的 , 下面我們就來看看 , 指針是怎么樣進行運算的 。我們以一個數組輸出為例 , 來驗證指針變量的運算 , 如下:
```c
void main() {
int arr[] = { 89,20,13,45,68 };
// 數組地址 , 默認是首個元素的內存地址
printf("輸出數組arr地址:%#x\n", &arr);
printf("這樣也可以獲取到數組的地址:%#x\n", arr);
printf("第一個元素的地址: %#x\n", &arr[0]);
int* p = &arr;
// 以普通的方式進行數組輸出
int i = 0;
for (; i < 5; i++)
{
printf("數組元素:%d\n", arr[i]);
}
printf("\n");
// 以指針運算的方式進行數組輸出
int j = 0;
for (; j < 5; j++)
{
printf("數組元素的值 : %d\n", *p);
p++;
}
printf("\n");
getchar();
}
````
從上述代碼我們可以看出 , 我們通過變量指針p進行`p++`操作 , 來獲取到數組中的值 , 這樣操作的可能是 , 因為數組存儲數據的內存空間是連續的 , 可以可以通過同類型的指針 , 進行指針運算來進行內存操作 , 值得注意的是 , 指針類型必須和數組類型一致 ,才能進行內存操作 。由此 , 我們可以得出指針為什么需要類型的答案了:
> 指針是存儲的地址是開始讀取的位置 , 類型是讀取的長度 , 操作類型必須一致 。
下面我們來做一個實驗 , 如果使用不同類型的指針來讀取數組 , 這樣操作會出現什么情況 , 我們將上述代碼的`int *p = @arr ;`更改為`float *p = &arr;`會出現什么情況呢 ? 結果如下:
```c
數組元素的值 : 0
數組元素的值 : 0
數組元素的值 : 0
數組元素的值 : 0
數組元素的值 : 0
```
我們使用`float`類型的指針 , 去操作int類型的數組 , 就完全取不到值了 。為什么會這樣呢 ? 我們一探究竟 , 打斷點去查看內存的 , 我們輸出一下指針變量的值 , 然后對照數組變量的地址,如下:
```c
指針變量存儲的值:0x101fdac -- 取值:0
數組元素:89 == 數組元素地址:0x101fdac
數組元素:20 == 數組元素地址:0x101fdb0
數組元素:13 == 數組元素地址:0x101fdb4
數組元素:45 == 數組元素地址:0x101fdb8
數組元素:68 == 數組元素地址:0x101fdbc
數組元素的值 : 0 == 指針存儲的地址:0x37064000
數組元素的值 : 0 == 指針存儲的地址:0x36e40000
數組元素的值 : 0 == 指針存儲的地址:0x36da0000
數組元素的值 : 0 == 指針存儲的地址:0x36f68000
數組元素的值 : 0 == 指針存儲的地址:0x37010000
```
我們可以看到 , 幾乎完全不一致了 , 地址都不相同了 , 我有一個疑惑 , 在第一次打印float指針變量值的時候 , 存儲的是數組第一個變量的內存地址 , 但是在循環遍歷的時候 , 卻不一樣了 , 目前不知道是什么原因導致的 , 有知道的希望告知一下 。上述輸出完整程序:
> 以上問題有一個答案了 , 雖然float和int類型都是四字節的 , 但是int 和 float的存儲方式不一樣 , 所有指針運算會出現不一樣 。
```c
void main() {
int arr[] = { 89,20,13,45,68 };
// 數組地址 , 默認是首個元素的內存地址
printf("輸出數組arr地址:%#x\n", &arr);
printf("這樣也可以獲取到數組的地址:%#x\n", arr);
printf("第一個元素的地址: %#x\n", &arr[0]);
//int* p = &arr;
float *p = &arr;
printf("指針變量存儲的值:%#x -- 取值:%f\n", p,*p);
int i = 0;
for (; i < 5; i++)
{
printf("數組元素:%d == 數組元素地址:%#x\n", arr[i],&arr[i]);
}
printf("\n");
int j = 0;
for (; j < 5; j++)
{
printf("數組元素的值 : %f == 指針存儲的地址:%#x\n", *p,p);
p++;
}
printf("\n");
getchar();
}
```
這次我們分析了指針在內存中的情況 , 以及指針變量的簡單運算 , 下次我們來聊聊 , 指針在方法中的運用 , 以及二級指針 。
Android程序員學C系列:
[C語言基礎及指針①](http://www.jianshu.com/p/4701cd1e1914)
[C語言基礎及指針②之指針內存分析](http://www.jianshu.com/p/d556070b12ef)
[C語言基礎及指針③函數與二級指針](http://www.jianshu.com/p/184df8a1f195)
[C語言基礎及指針④函數指針](http://www.jianshu.com/p/181b50e02c89)
[C語言基礎及指針⑤動態內存分配](http://www.jianshu.com/p/93db7c692d1b)
[C語言基礎及指針⑥字符操作](http://www.jianshu.com/p/b7e6fc094087)
[C語言基礎及指針⑦結構體與指針](http://www.jianshu.com/p/36cc18151e87)
- 簡介
- C語言基礎及指針①語法基礎
- C語言基礎及指針②之指針內存分析
- C語言基礎及指針③函數與二級指針
- C語言基礎及指針④函數指針
- C語言基礎及指針⑤動態內存分配
- C語言基礎及指針⑥字符操作
- C語言基礎及指針⑦結構體與指針
- C語言基礎及指針⑧文件IO
- C語言基礎及指針⑨聯合體與枚舉
- C語言基礎及指針⑩預編譯及jni.h分析
- JNI開發系列①JNI概念及開發流程
- JNI開發系列②.h頭文件分析
- JNI開發系列③C語言調用Java字段與方法
- JNI開發系列④C語言調用構造方法
- JNI開發系列⑤對象引用的處理
- NDK開發基礎①使用Android Studio編寫NDK
- NDK開發基礎②文件加密解密與分割合并
- NDK開發基礎③增量更新之服務器端生成差分包
- C++基礎①命名空間結構體和引用