40 C 语言中的指针
C 语言的指针常常被人们认为是 C 语言中的灵魂所在,可以完成很多高难度的操作。但是更多的人感觉 C 语言的指针的存在如同噩梦一般,因为稍不注意,就会引起灾难性的后果。
不管你是不是喜欢 C 语言中的指针,我们都要学习这种看起来很神奇的东西。因为指针这个概念不是 C 语言首创的,而是苏联的计算机科学家首创的。
1. 什么是指针?
指针是什么?这是来自灵魂的拷问。其实指针也是一种变量。我们之前也说过。只不过存储的是另外一个变量的地址。变量地址是变量在内存中存储的位置索引。
int *a;
int b=5;
a = &b;
这里我们定义了一个整数类型的指针 a
,可以看出指针的定义与变量的声明是一致的,只不过需要在变量明前加上一个额外的字符 *
。
由于指针中存储的应该是变量的地址,因此我们在赋值的时候需要获得变量的地址,而不是变量本身所存储的数值。这里我们采用的 &
来获取变量的地址。将获取到的地址赋值给指针变量。
要是想使用指针中存储地址中所存储的值,那么就需要在指针变量名前加 *
来获取相应地址中存储的值。
2. 示例程序
#include <stdio.h>
int main()
{
int *a, b = 100, *c;
printf("a value = %p, a address = %p, a point value = %dn", a, &a, *a);
printf("b value = %d, b address = %pn", b, &b);
printf("c value = %p, c address = %p, c point value = %dn", c, &c, *c);
a = &b;
printf("a value = %p, a address = %p, a point value = %dn", a, &a, *a);
c = a;
printf("c value = %p, c address = %p, c point value = %dn", c, &c, *c);
printf("b value = %d, b address = %pn", b, &b);
return 0;
}
运行结果:
示例中的运行结果中的十六进制所表示的地址每台机器都会不太一样,甚至每次运行都会发生变化。因为操作系统每次为系统分配的内存都不太一样。
a value = 0x7fffaf0005a0, a address = 0x7fffd2942a28, a point value = -1991643855
b value = 100, b address = 0x7fffd2942a24
c value = 0x7fffd2942b20, c address = 0x7fffd2942a30, c point value = 1
a value = 0x7fffd2942a24, a address = 0x7fffd2942a28, a point value = 100
c value = 0x7fffd2942a24, c address = 0x7fffd2942a30, c point value = 100
b value = 100, b address = 0x7fffd2942a24
示例程序中声明了一个整数类型的指针 a
,同时还声明并初始化了一个整数类型的变量 b
。
我们首先展示了此时此刻指针变量 a
中存储的值,也就是一个内存地址,这个地址为 0x7fffaf0005a0
,同时 a
变量本身的地址为 0x7fffd2942a28
,此时其存储的内存地址中所存储的值为 -1991643855
。这里需要说明的是, a
变量此时还没有初始化,没有赋值,里面存储的数值是随机的,所以其代表的值也是随机的,必须在赋值以后才能使用。这点和所有的变量的使用是一致的。
变量 b
的存储的数值为 100
,其内存的地址为 0x7fffd2942a24
。
指针变量 c
中存储的数值是地址 0x7fffd2942b20
,其本身的地址是 0x7fffd2942a30
,里面存储的地址中存储的数值为 1
。
然后我们进行了一次赋值的操作。这里的赋值操作,就是将变量 b
的地址赋给了变量 a
。
这个时候你会发现变量 a
中存储的数值变成了变量 b
的地址,而变量 a
自己的地址是没有发生变化的,而变量 a
中所存储的地址中的值也编程了变量 b
中所存储的值 100
。
指针之间的赋值就比较直接,和普通变量的赋值是一样的,只要直接赋值就可以了。
下面的表格展示了这一系列的变化
初始状态
变量名 | 变量中数值 | 地址 | 指针地址中数值 |
---|---|---|---|
a | 0x7fffaf0005a0 | 0x7fffd2942a28 | -1991643855 |
b | 100 | 0x7fffd2942a24 | |
c | 0x7fffd2942b20 | 0x7fffd2942a30 | 1 |
赋值后
变量名 | 变量中数值 | 地址 |
---|---|---|
a | 0x7fffd2942a24 | 0x7fffd2942a28 |
b | 100 | 0x7fffd2942a24 |
c | 0x7fffd2942a24 | 0x7fffd2942a30 |
3. 小结
指针作为 C 语言中相对比较抽象的部分,是很多初学者最难逾越的部分。但是请大家放松心情。因为指针其实和普通变量没有什么本质的区别,其实叫做指针变量更为贴切一点。指针是一个变量,里面存储的内容是另外一个变量的内存地址。每个变量都会有地址,包括指针变量自己本身也是有地址存在的。我们在赋值的时候是将别的变量通过变量名获得的该变量的地址存储到指针变量里,而后获取这个被存储到指针变量里的地址的数值,或者继续将该变量的地址赋值给另外一个指针变量。指针变量的存在只是一个变量的赋值,切记理解为玄学。