C语言指针笔记

C语言指针是难点,是必须要攻克的堡垒。

看C语言的资料,指针是绕不过去的,这里记录自己对指针的理解。

一、感性认识指针。
0、有如下C代码,存为point.c文件

#include <stdio.h>

int main()
{
	int num = 1;
	int *point;

	point = &num;

	// %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语言利用指针在函数中交换两个数的思考

发表评论

电子邮件地址不会被公开。 必填项已用*标注