c primer plus关于指针的总结
指针就是值为内存地址的变量
主要包括
1 指针的基本使用
2 指针与函数
3 指针与数组的关系
4 函数,数组和指针
5 指针与多维数组
6 数组指针
7 指针数组
8 函数指针
1 指针的基本使用
int a=1;
int b = 2;
int* ptr;//声明一个指针变量
ptr = &a;//将a的地址赋给ptr,此时ptr指向a,ptr与&a的区别是ptr是变量,而&a是常量,ptr可以修改
ptr = &b;//此时ptr改变了原有的指向位置,指向了b,ptr的值是b的地址
int val = *ptr;//注意此时的*与第一次*意义不一样,第一次是说明ptr是一个指针变量,而此时的*是对ptr进行解引用
//相当于取ptr这个地址里面的东西
printf("&a=%p,&b=%p,ptr=%p,&ptr=%p,*ptr=%d", &a,&b,ptr,&ptr,*ptr);//打印
//打印结果如下&a=012FF868,&b=012FF85C,ptr=012FF85C,&ptr=012FF850,*ptr=2 注意ptr与&b的值一样,
//因为两者本身就是同一块地址,但是&ptr不一样,这是ptr本身的地址
2 指针与函数
我们都知到在函数中改变传入数值在主函数用也发生改变可以使用返回值,但是这样只能返回一个值,如果要改变两个此时用指针就可以很好解决这个问题了
void change(int* p, int* q) {
int temp;//注意交换的两个数本身是int类型
temp = *p;
*p = *q;
*q = temp;
}
int main(void) {
int a=1;
int b = 2;
change(&a, &b);//注意传递什么类型就要用什么类型接收
printf("%d,%d", a, b);
return 0;
}
此时a与b的值在主函数内也发生了改变
3 指针与数组的关系
如果flizny是一个数组,那么下面的语句是成立的
flizny == &flizny[0];//两个都表示数组首元素的地址
注意指针加一的地址不是下一个字节的地址,而是下一个元素的地址
int flizny[5] = { 0 };
printf("%p,%p,%p,%p",flizny, &flizny[0], flizny + 1, &flizny[0] + 1);
//打印结果如下 00AFFBBC, 00AFFBBC, 00AFFBC0, 00AFFBC0
//加一的差值即00AFFBC0- 00AFFBBC=4,指针加一的地址不是下一个字节的地址,而是下一个元素的地址
//,大小与指针类型有关
下列等式成立
flizny + 2 = &flizny[0] + 2;
*(flizny + 2) = flizny[2];
这里需要注意*(flizny + 2)与*flizny + 2是不一样的,*的优先级大于+
4 函数,数组和指针
total = sum(marbles);//函数调用,marbles是一个数组
int sum(int* ar) {
int i;
int total = 0;
for (i = 0; i < 10; i++) {
total += *ar;
ar++;
}
return total;
}
int sum(int ar[]) {
int i;
int total = 0;
for (i = 0; i < 10; i++) {
total += ar[i];
}
return total;
}
使用都是一样的
但是两个大小是不一样的,指针的大小是4个字节或8个字节,根据系统而不同,数组的大小看数组类型和数组元素个数。
假设
int urn[3];
int* ptr1, * ptr2;
下面是一些有效和无效的语句
ptr1++;有效
ptr2 = ptr1 + 1; 有效
ptr2 = urn + 1; 有效
urn++;无效,数组名是一个指针常量,不允许加减操作
ptr2 = ptr1 + ptr2;
ptr2 = urn * ptr1;
const 修饰符,设置不能更改
int const* p==const int *p//*p,即不能更改
int * const //地址不能更改,即p不能更改
int const* const p//都不能改
5 指针与多维数组
int zippo[4][2];
zippo的值与& zippo[0]的地址相同:zippo[0]本身是一个内含两个整数的数组,
所以zippo[0]和他首元素(& zippo[0][0])的地址相同
也就是说,zippo[0]是一个占用一个int大小对象的地址,而zipp0是一个占用两个int大小对象的地址,所以zippo与
zippo[0]的地址相同。
注意:指针加一对每一个都不同, 一个加一个int对象,一个加两个int对象
解引用一个指针:* (zippo[0]) == zippo[0][0], 因为zippo[0] == &zippo[0][0];
**zippo第一次解引用获取zippo[0][0]的地址,第二次获取zippo[0[0]地址的值
zippo=zippo[0]=&zippo[0][0]
6 数组指针
本质是一个指针
int zippo[4][2] = { {2,4},{6,8},{1,3},{5,7} };
int(*pz)[2];//一个指针指向一个包含两个int元素类型的数组
pz = 0x0064fd38 pz + 1 = 0x0064fd40//相差8个字节,两个元素
pz[0] = 0x0064fd38 pz[0] + 1 = 0x0064fd3c//相差4个字节,一个元素
* pz = 0x0064fd38 * pz + 1 = 0x0064fd3c
pz[0][0] = 2;
*pz[0] = 2;
**pz = 2;
*(*(pz+2)+1)=3
7 指针数组
本质是一个数组,里面存放指针
char* name[5] = {
"zhang san",
"li si",
"wang wu",
"wang w1",
"wang w2"
};
printf("%s", name[1]);
//打印li si
8 函数指针
char mis[] = "shajdbhjhs";
void toupper(char*)//函数原型
void (*pf)(char*);//pf是一个指向函数的指针,改函数带有一个char*的参数,函数无返回值
pf = toupper;//将函数地址传给pf
(*pf)(mis);//通过*pf调用函数,相当于toupper(mis);pf指向toupper函数,*pf相当于toupper函数,所以两者相同
pf(mis)//同样可以,函数名是指针,那么指针和函数名可以互换使用,两者相同