简介
本质:指针是一个值为内存地址的变量。
假设一个指针变量名为ptr:
ptr = &pooh; // 把pooh的地址赋值给ptr
我们可以说,把ptr指向pooh.即ptr为变量,&pooh为常量。
间接运算符:*
ptr = &bah;
val = *ptr; // 找出ptr指向的值赋值给val
归纳上面的两句可以得到:
val =bah;
指针的声明
声明一个指针变量时一定要指定指针所指的变量的类型,因为不同的变量类型占用不同的存储空间。
int *pi; // 指向int类型变量的指针
char *pc; // 指向char 类型指针
float *pf,*pg; // 指向浮点类型指针
2.4 指针在函数中的通信
我们首先来看两个栗子:
输出结果为:
输出结果为:
因此,我们可以做到把变量的两类信息传递给函数:
function1(x);//要求参数是必须跟x一个数据类型;
function1(&x);// 要求参数必须指向一个正确类型的指针。
因此如果要在被调函数中改变主调函数的变量,需要用第二种形式。
指针与数组
flizny == &flizny[0]; //数组名也可以表示数组首元素地址
下面先看看一个例子:
输出结果如下:
总结:在C中,指针加1是增加一个存储单元,对数组来说,这意味着把加一后的地址就是下个元素的地址,即:
dates + 2 == &dates[2]; // 相同地址
*(dates +2) == dates[2]; //相同的值
注意
*(dates +2) // dates的第三个元素的值
*dates +2 // dates的第一个元素加2
函数,数组和指针
函数在在声明数组形参时可以省略数组名,下面几种原型是等价的:
int sum(int *ar,int n);
int sum(int *,int);
int sum(int ar[],int n);
int sum(int [],int);
函数在定义时,不能省略参数名,下面几种定义师等价的:
int sum(int *ar,int n){
}
int sum (int ar[],int n){
}
指针操作
先看一个例子:
输出结果为:
总结
赋值: ----- 地址应该和指针类型兼容,也就是说不能把double类型的地址赋值指向int类型的指针。
取址: ------指针变量也有自己的地址和值,&运算符可以取到指针本身的地址,上例中0x7fff5fbff7e8的地址上,存储的是0x7fff5fbff800,即urn的地址,因此&ptr1是指向ptr1的指针,而ptr1是指向utn[0]的指针。
指针求差:-----通常, 求差的两个指针的两个指针分别指向同一个数组的不同元素,这样计算可以求出两个元素之间的差值,上例中两者之差是2,表示两个指针指向的元素相差2个int。
解引用未初始化的指针:
int *pt; // 未初始化的指针
*pt =5; // 出现错误
指针与多重数组
int zippo[4][2]; // 内含int 数组的数组
zippo与&zippo[0]的值相同,前者是占有2个int大小对象地址,后者就一个int大小地址,因为开始地址相同所以值相同。
zippo +1 与zippo[0]+1值不同
*(zippo[0]) 表示存储在zippo[0][0];
*zippo 和&zippo[0][0]是等价的
**zippo 和*&zippo[0][0]等价
下面看个具体的例子:
zippo[0]+1 // 地址增加4个字节
zippo +1 // 地址增加八个字节
zippo[2][1]等价写法:*(*(zippo +2)+1)
下面进行分析:
zippo+2 //表示二维数组第三个元素
*(zippo +2) //第三个元素的首元素地址
*(zippo +2) +1 // 第三个元素的第二个元素地址
*( *(zippo +2) +1) // zippo[2][1]
指向多维数组的指针
int (*pz)[2] ; //pz指向一个内含2个int 类型的值的数组
int *pz[2]; // pax是一个内含两个指针元素的数组,每个元素都指向int 的指针
下面看个例子
总结:
zippo[m][n] == *(*(zippo+m)+n);
pz[m][n] == *(*(pz+m)+n)
函数与多维数组
声明函数形参如下:
void somefunction(int (*pt)[4]);
也可以第一个括号是空的,但第二个不可以
void somefunction (int pt[][4]);
以上内容为本人学习笔记,相关示例参考《C Primer Plus》(第6版)中文版。