续接上篇 [C语言基础及指针①](http://www.jianshu.com/p/4701cd1e1914)
在上一篇中 , 我们了解了C语言的基本语法 , 以及简单指针 , 也知道 , 指针是C语言的核心 , 那么我们今天就来简单剖析一下指针 , 了解他是怎么的神奇 。
> 今天是七夕 , 祝各位情人节快乐 。
指针的基本写法是`int i = 10 ; int *p = &i ;` , 由此我们可以看出 , 指针和变量类似 , 其实 , 指针也是变量 , 我们`printf("%#x",p)` , 输出的就是i的地址值 , p就是一个变量 , 只是这个变量不普通 , 他可以通过他里面地址 , 操作这个地址里面的内容 , 这就是其强大之处 。那么他在内存中是怎样的呢 ? 下面我们来看看 。
![指针操作内存图.png](http://upload-images.jianshu.io/upload_images/643851-13e6b0654e0c503c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
由图上我们可知 , 指针变量就是用来操作内存空间的 , 当然也可以作为变量存储 , 例如`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++基础①命名空间结构体和引用