C语言指针是难点,是必须要攻克的堡垒。
看C语言的资料,指针是绕不过去的,这里记录自己对指针的理解。
一、感性认识指针。
0、有如下C代码,存为point.c文件
#include <stdio.h> int main() { int num = 1; int *point; point = # // %p表示输出地址 printf("&num = %p | point = %p | *point = %d \n", &num, point, *point); }
2、在Mac下编译、执行
MacBook-Pro:c chuanbo7$ cc point.c MacBook-Pro:c chuanbo7$ ./a.out &num = 0x7fff540f3b0c | point = 0x7fff540f3b0c | *point = 1
3、代码说明
3.1、变量前面加&符表示取变量内存地址。
如上,&num对于的内存地址是0x7fff540f3b0c
3.2、*是指针的标志,变量前面加*就表示这个变量是指针变量。
如上,*point就表示一个指针变量
3.3、如果*point是指针变量,point表示取内存地址,*point表示取point中内存地址对应的变量(可以说是取地址指向的值,或者通过地址找到值)
二、什么是指针。
0、指针是变量。
指针是一种特殊的变量,普通变量存储的是值,指针变量中存储的是内存地址。
1、指针不是数据类型。
很多资料显示指针是一种数据类型,如果是一种类型,为啥不用这种类型来定义变量呢?个人认为*point是整型指针变量更好理解。
三、实例理解指针,交换两个数。
#include <stdio.h> void swap(int *px, int *py); int main() { int x = 100; int y = 99; swap(&x, &y); printf("x = %d | y = %d \n", x, y); return 0; } void swap(int *px, int *py) { int tmp = *px; *px = *py; *py = tmp; }
以上代码保存文件sawp.c, 编译执行,结果如下:
MacBook-Pro:c chuanbo7$ cc swap.c MacBook-Pro:c chuanbo7$ ./a.out x = 99 | y = 100
达到交换的目的了。
原理:我们利用指针间接访问变量,在对变量进行交换。
原理图:
如果swap函数是下面这样,则达不到交换的目的:
void swap_common_fail(int x, int y) { int tmp = x; x = y; y = tmp; } void swap_pointer_fail(int *px, int *py) { int *tmp = px; px = py; py = tmp; }
为了达到交换的目的,为什么要用指针,以及swap_error为啥错误,开始也困扰了我很久,后来我想到了一个比方说服了自己,希望也能说服你。
这个比方我称之为“指针池塘”
场景描述:
有一个池塘,从中间一分为二,一边有一条三文鱼,一边有一条耗儿鱼,中间隔着网,鱼🐟本身不能穿越。我们想把这两条鱼互换。
方案一、我们下到池塘,分别抓住两条鱼,然后互换。这种方式特别好理解,此时鱼和我们在一个区域,如同我们直接在main主调函数中交换两个数
int main() { int x = 100; int y = 99; int tmp = x; x = y; y = tmp; printf("x = %d | y = %d \n", x, y); return 0; }
方案二、我们不能下水(不会游泳),我们可以通过两个鱼竿,分别把两条鱼钓起来,放到对方的池子
原理解释:
0、一个鱼竿上写着三文鱼竿,另一个写着耗儿鱼竿,相当于两个地址 1、2个鱼竿分别指向了2条鱼,相当于2个指针分别指向2条鱼。 2、由于光线折射,我们把肉眼看到的2条鱼(不是鱼本身)钓起来做了交换,真实的鱼并没有受到影响,所以交换失败。如同函数swap_common_fail。 3、鱼还没有上钩,我们把鱼竿上【三文鱼鱼竿】的标签和【耗儿鱼鱼竿】的标签撕下来互换,我们很清楚鱼并不会交换。如同函数swap_pointer_fail。 4、我们需要通过两个鱼竿,分别把鱼钓起来互换,就能真实的达到交换的目的。鱼竿类似指针,我们通过鱼竿触摸到真实的鱼,如同主调函数main通过指针获取变量的值一样,间接达到交换目的。
我们把成功交换之后变量的地址打印出来,发现地址是没变的,只是值变了。如同池塘不会变,只是鱼移动了位置。
int main() { int x = 100; int y = 99; printf("addr_x = %p | addr_y = %p \n", &x, &y); swap(&x, &y); printf("addr_x = %p | addr_y = %p \n", &x, &y); printf("x = %d | y = %d \n", x, y); return 0; }
MacBook-Pro:c chuanbo7$ cc swap.c MacBook-Pro:c chuanbo7$ ./a.out addr_x = 0x7fff5b143b08 | addr_y = 0x7fff5b143b04 addr_x = 0x7fff5b143b08 | addr_y = 0x7fff5b143b04 x = 99 | y = 100
未完待续…
参考:
《C程序设计语言》布莱恩&丹尼斯
How do pointer to pointers work in C?
What do people find difficult about C pointers?
Simple swap function…why doesn’t this one swap?
C语言利用指针在函数中交换两个数的思考