简单理解指针
*
与&
相互作用:*&a
实际上就是a
变量
- 是C语言的优势,指针也就是地址
定义格式
类型 *指针变量名;
或类型* 指针变量名;
说明
- 指针变量的类型是他指向内存单元中存放的数据类型
- 指针变量必须被赋值语句赋值初始化后才能使用,否则,严重的话会死机
- 可初始化为
0
,NULL
(不指向任何值)或者某个地址 - 指针变量只能接受地址,赋以数据会错误
引用
- 在指针引用前,要定义,赋值,否则,会造成系统混乱
指针运算符
取址符&
- 单目运算符,结合性自左向右.
取内容符*
- 也叫间接引用运算符,结合性自左向右,且*后面只能是指针.
- 指针的值也可以改变,也就是改变指向.
指针的类型
- 不同类型的指针不能相互赋值(虽然没问题)
1 | int* a = NULL; |
如果*a=0
,则*b[0]-*b[3]
都会变成0
指针类型的转换
void*
表示不知道指向什么东西的指针:int *p = &i; void*q = (void*)p;
- 并没有改变
p
所指的变量类型,而是用不同的眼光通过p
去看它所指的变量q
此时认为p指向的变量不是int
,而是void
- 并没有改变
场景1
利用函数交换数值(也就是说传给主函数多个数值)
1 |
|
场景2
1.函数返回运算状态,指针返回结果
2.当要返回的值多个都是有效的结果时,要分开返回了
*p和p
*p
是常量,p
是变量
指针与数组
注意:函数参数表的数组其实就是指针
- 以下四种函数原型是等价的
int sum(int *a, int b)
int sum(int*, int)
int sum(int a[], int b)
int sum(int [], int)
数组就是特殊的指针
[]
对指针和数组都可以用,同理*
也一样
因为
int a[]<==>int *const a=
所以这里不能被赋值
如
a = b;//error
一维数组指针
1 | int a[10]; |
在C语言中规定数组名代表数组中的首地址(声明函数的参数不是,他不占实际内存单元)
实际上p=&a[0]
与p=a
一样
- 但是数组的单元表达的是变量,需要
&
取地址- 意思是把数组的首地址赋给p
p+1
实际是p+1*d
,d
代表字节数
综上,引用数组元素的方法有
- 下标法:
a[0]或p[0];
- 指针法:
*(a+i)
或者*(p+i);
a是数组的首地址,即指针常量
- 因为数组元素也是内存变量,所以此类指针的定义和使用和指向变量的指针变量相同.
1 | int a[10] *p; |
- 此时
p
指向a[0]
,下面可以用p
表示数组元素.- 下标表示:
1 | p[0],p[1],...//需要定义指针数组 |
- 指针表示法:
1 | *(p+0),... |
- 注意:使用指针变量引用数据时,必须关注当前值
- 比如:若
p=p+3
,则p[0]
代表a[4]
- 比如:若
二维数组指针
1 | int a[3][4]; |
a
是首地址三个行元素的地址分别是:
a,a+1,a+2
且a[0],a[1],a[2]
也是地址量,即*(a+0),*(a+1),*(a+2)
是一维数组的首个元素的地址
每个元素的地址&a[i][j],a[i]+j,*(a+i)+j
都可以表示
元素的表示a[i][j],*(a[i]+j),*(*(a+i)+j)
可以表示
要使用这两种方法引用元素的前提是二维数组全赋给指针数组
1
2 int (*p)[3], a[2][3];
p = a;注意:
()
不能去掉,因为[ ]
的优先级高于()
- 意思是一个指向二维数组的指针,只占int的字节数
type *p[num
]的意思是一组指针,每个元素保存一个指针
- 等价关系
a+i == p+i
a[i] == p[i] == *(a+i) == *(p+i)
a[i][j] == p[i][j] == *(a[i]+j) == *(p[i]+j) == *(*(a+i)+j) == *(*(p+i)+j)
说明:
- 赋给指针时首地址是
a[0]
,**a
表示a[0][0]
初始化的方法
方法一
1 | char a[] = {0,1,3,4,5,6,7,8,9,-1}; |
方法二
1 | char a[] = {0,1,3,4,5,6,7,8,9,-1}; |
错误表达
1 | char a[] = {0,1,3,4,5,6,7,8,9,-1}; |
算术操作及比较
只可以作加减法
p+n
指的是p
指向的数据单元之后的第n
个数据单元int *p;
(设p
的初始值是2000
)p+1;
表示2002
指针值的比较(
<,<=,>,>=,==,!=
)前提条件:
p1
和p2
是同一类型的指针变量,并且都指向同一段连续的储存空间则
p1<p2
为真的话结果是1,否则是0
数组是递增排列的,
a[0]>a[1]
CONST
1.只有C99以后的支持
1 | int * const q = &a; |
- 此时
q
被固定,q++
不能实现;
1 | const int *q = &a; |
q
可以被赋地址,但*q
不能被赋值
2.非const
转换为const
1 | 针void f(const int* x); |
- 适用于传递的参数类型比地址大时
3.const
数组
1 | const int a[] = {1,2,3}; |
此时每个单元都是const
,
只能通过初始化赋值,
因为把数组传入函数时是地址,所以函数可以修改数组的值
为了保护数组不被破环,可以设置参数为
const
1 | int sum(const int a[ ] ); |
0地址
通常
0
地址不能乱碰你的指针不应该有0值
0
地址可以来表示特殊的事情- 返回的指针是无效的
- 指针没有真正初始化
NULL
是一个预定的符号,表示0
地址一般用
NULL
表示0
地址
作用
传入较大的数据时用作参数
传入数组后对数组进行操作
返回多个结果
- 修改多个变量
动态申请内存