C学习笔记(十一):指针详解
一、为什么需要指针?
普通变量保存的是:
数据本身。
例如:
int a = 10;变量a中保存:
10但是计算机在内存中存储数据时,每个数据都有自己的存储位置。
例如:
内存: 地址 数据 0x1000 10其中:
10是数据;0x1000是数据存储的位置。
这个位置称为:
地址。
指针的作用:
通过地址直接访问内存空间。
因此:
指针可以让程序:
更高效;
更灵活;
更方便地操作内存。
二、内存地址
1. 什么是地址?
计算机为了区分不同的内存空间,会给每个内存空间编号。
这个编号就是:
内存地址。
例如:
地址 数据 1000 20 1004 30程序通过地址找到对应的数据。
2. 内存按字节编址
计算机中的内存:
按字节进行编号。
例如:
0x0000 0x0001 0x0002 0x0003 ...每一个地址对应一个字节空间。
三、指针的概念
1. 什么是指针?
指针:
可以理解为地址。
地址就是指针。
例如:
变量:
int a = 10;假设:
a所在地址: 0x1000那么:
0x1000就是变量a的指针。
2. 指针变量
用于保存地址的变量:
称为:
指针变量。
例如:
int *p;表示:
定义一个指向int类型数据的指针变量p。
关系:
普通变量 a ↓ 保存数据10 指针变量 p ↓ 保存地址0x1000四、取地址运算符 &
1. 功能
&:
获取变量的地址。
例如:
int num = 10; printf("%p",&num);输出:
num的地址2. 使用规则
只有:
左值
才能进行取地址操作。
例如:
正确:
&a错误:
&10原因:
常量没有存储空间。
3. 类型变化
例如:
int a;a类型:
int执行:
&a之后:
类型变为:
int *即:
int类型指针。
五、取值运算符 *
1. 功能
*:
根据地址访问对应空间的数据。
例如:
int a=10; int *p=&a;此时:
p ↓ a的地址使用:
*p表示:
访问a中的数据。
结果:
102. 修改变量值
例如:
int a=10; int *p=&a; *p=20;执行后:
a变为:
20原因:
*p代表p指向的空间。
3. 类型变化
例如:
int *p;执行:
*p类型:
int即:
指针类型降级。
六、指针变量定义
格式:
数据类型 *变量名;例如:
int *p; char *q; float *r; double *s;表示:
不同类型的指针。
指针变量大小
无论什么类型:
int * char * float * double *指针变量本身大小都是:
8字节
因为保存的是地址。
七、野指针
1. 什么是野指针?
野指针:
未初始化的指针,或者指向已经释放空间的指针。
例如:
int *p; *p=10;此时:
p没有指向有效空间。
程序可能崩溃。
2. 如何避免?
定义指针后:
不要直接使用。
应该:
int a; int *p=&a;或者:
int *p=NULL;八、空指针 NULL
空指针:
指向地址0的指针。
例如:
int *p=NULL;表示:
p暂时不指向任何有效空间。
注意:
不能:
*p=10;因为:
NULL地址不可访问。
会导致:
程序崩溃。
九、指针类型
不同类型指针:
int *p; char *p; float *p; double *p;区别:
指向空间的数据类型不同。
例如:
int *p;表示:
p指向4字节整数空间。
十、指针的算术运算
指针支持:
++
指针相减
1. 指针++
例如:
int *p; p++;不是增加1字节。
而是:
增加:
sizeof(int)个字节。
例如:
int占4字节:
地址: 1000 ↓ 10042. 指针--
类似:
向低地址移动。
3. 指针相减
例如:
p1-p2得到:
两个地址之间相差多少个元素。
十一、指针操作
指针有两种操作方式。
1. 修改指针本身
例如:
p=&b;改变:
p的指向。
2. 修改指针指向的数据
例如:
*p=100;改变:
指向空间中的值。
示例:
int a=100; int b=200; int *p=&a; p=&b;改变:
p指向b。
而:
*p=300;改变:
b的值。
十二、指针作为函数参数
前面学习函数传参:
默认是:
值传递。
1. 值传递
例如:
void change(int a) { a=100; }调用:
int x=10; change(x);结果:
x仍然是:
10因为:
形参只是副本。
2. 地址传递
如果想修改外部变量:
需要传地址。
例如:
void change(int *p) { *p=100; }调用:
int x=10; change(&x);执行后:
x=100地址传递作用:
修改函数外部变量;
一个函数返回多个结果。
十三、数组与指针关系
C语言中:
数组名本质上是指向数组第一个元素的指针常量。
例如:
int a[5]={1,2,3,4,5};数组名:
a等价于:
&a[0]例如:
int *p=a;表示:
p指向数组第一个元素。
访问:
a[2]等价于:
*(a+2)也等价于:
*(p+2)十四、一维数组指针传参
数组作为函数参数:
例如:
int fun(int array[],int len);等价于:
int fun(int *array,int len);示例:
冒泡排序函数:
void BubbleSort(int *array,int len) { }调用:
BubbleSort(a,10);数组地址传入函数。
注意:
数组传参时:
函数中操作的数组:
和外部数组:
是同一个空间。
因此可以直接修改数组内容。