C语言指针的个人见解(一)

C语言指针的个人见解(一)


关于内存

内存基础

1位 = 1bit = (0, 1)
1字节 = 8位(一般情况下)
一般来讲,可以把一个字节当成最小寻址单位,也就是最小的可以区分的、可以定位的一个内存。
8位,也就是28种数据,也就是256种,如果是无符号整形数据的话就是0~255。

C语言变量的内存与变量地址

而在C语言中,假如有一个int类型的值(int_32),那么int应当是有四个字节的存储空间。

1
int a = 2;

声明并初始化一个名为a的变量,那么a就被分配了4个字节的存储空间,并让a的值为2。

使用%p说明符可以查看一个指针指向的地址。

1
2
char *pa = &a;//注意此处使用的是char*,而不是int*
printf("a的地址为:%p %p %p %p\n", pa, pa + 1, pa + 2, pa + 3);

可以看到以下输出

1
a的地址为:00EFFC14 00EFFC15 00EFFC16 00EFFC17

条件一:上面说过,最小寻址单位是字节,那么一个地址变量==一个字节
条件二:一个char型变量是大小为一个字节的变量(因为ASCII码只有128个)
结论:(一个地址变量==一个字节)==(一个char*指针==一个最小的寻址指针)

所以上面四个十六进制数就是变量a的四个字节的地址,可以看到他们是连续的。

关于指针

指针

上面的尝试使用了char*当辅助工具。

那如果换用int 指针,而不是char指针呢?

1
2
3
char *char_pa = &a;//注意此处使用的是char*,而不是int*
int *int_pa = &a;
printf("a的地址为:%p %p %p %p\n%p", char_pa, char_pa + 1, char_pa + 2, char_pa + 3, int_pa);

结果应该是

1
2
a的地址为:00EFFC14 00EFFC15 00EFFC16 00EFFC17
00EFFC14

可以看到int_pa和char_pa的输出结果是一样的。

那么结论是:一个指针变量的值永远是它指向的变量的第一个字节的地址。

指针类型

从上面的例子可以看到,char_pa和int_pa的值其实是一样的,但是两个指针的类型不同,值一样是因为上面的结论。

那么指针的类型有什么用呢?

1
2
3
4
5
int a = 1;
int *int_pa = &a;
char *char_pa = &a;
printf("char_pa:%p char_pa+1:%p\n", char_pa, char_pa + 1);
printf("int_pa:%p int_pa+1:%p\n", int_pa, int_pa + 1);

1
2
char_pa:007FFE20 char_pa+1:007FFE21
int_pa:007FFE20 int_pa+1:007FFE24

可以看到
char_pa+1的时候,地址变量增加了一个单位
int_pa+1的时候,地址变量增加了四个单位

回想一下
char类型是一个字节,需要一个单位来存储
int类型是四个字节,需要四个单位来存储

所以结论:

  1. 指针类型标记了指针做增减的时候移动的地址单位长度。
  2. 指针增减的长度为指针指向的变量的类型的字节数。
  3. 指针增减的长度恰好够指针跳出当前指向的变量,从而指向下一个变量。

也就是说,如果a,b的地址如下所示

1
2
a:007FFE20 007FFE21 007FFE22 007FFE23
b:007FFE24 007FFE25 007FFE26 007FFE27

那么int_pa++之后,int_pa就指向变量b了(同样的,指针的值还是b的第一个字节的地址,也就是007FFE24)
这个时候 *int_pa 就可以拿到b的值

好了,开始拖更