指针是 C 语言的重要组成部分,可以说是 C 语言的灵魂。所谓指针用得好,编程没烦恼。但是指针不太好掌握,我也是曾经被指针虐待千百遍,可我依然待她如初恋。在此我整理一下我对于指针的理解。
指针,是一个存放地址的变量
指针是一个单变量,存放着内存地址,她的大小是由计算机系统地址宽度所决定。简单来说,32位系统,指针的大小就是 4 Byte。64位系统,指针的大小就是 8 Byte。在同一系统中,所有类型的指针大小都一样。不管她是 void* 指针,char* 指针,还是函数指针,统统都是 4 或者 8 Byte。具体代码:
char* p1;
int* p2;
float* p3;
double* p4;
void* p5;
printf("\n");
printf(" p1 指针的size: %d \n", sizeof(p1));
printf(" p2 指针的size: %d \n", sizeof(p2));
printf(" p3 指针的size: %d \n", sizeof(p3));
printf(" p4 指针的size: %d \n", sizeof(p4));
printf(" p5 指针的size: %d \n", sizeof(p5));
输出:
指针,是有形状的
这里的形状是指指针在内存操作的有效范围,这个就是指针的类型有关了。例如,char* 指针能操作 8 个 bit 的内存,而 int* 指针能操作 32 个 bit 的内存。举个形象一点的例子:有两个手电筒,一个口径是1,另一个口径是4,那么它照在墙上的光斑的大小和不一样。
具体代码:
// 此处 a 的内存分布为:
// 00000001 00000001
int a = 257;
int *b = &a;
char *c = &a;
printf("\n");
printf(" b 指针的值: %p \n", b);
printf(" c 指针的值: %p \n", c);
printf(" *b 的值: %d \n", *b);
printf(" *c 的值: %d \n", *c);
输出:
由上图所示,指针 b 与 c 的地址是一样的,但是 b 与 c 指针的有效内存访问范围不同,所以从同一内存地址中能拿到的内容也不一样。
指针的运动
上述所说,指针是变量。那么意味着指针可以做运算。但是指针只能做加减运算,不能做乘除运算。指针的加减运算,意味着指针值整体偏移,偏移的量的由定义这个指针的类型而决定:
- 当指针是指向单个变量时,他的偏移量就是,定义它的变量类型的大小
int *p;
p = 100; // p == 0x100
p++ // p == 0x104, sizeof(int) 是4,所以偏移4。
long *p1
p1 = 100 // p1 == 0x100
p1++ // p1 == 0x108, sizof(long) 是8,所以偏移8。
int *p2
p2 = 100 // p2 == 0x100
p2+5 // p2 == 0x100 + 4 * 5 = 0x120, 偏移5个sizeof(int)。
- 当指针指是一个数组指针,那么她的偏移量就有点复杂。她偏移量为该数组的最后一维度到数组第二维度的乘积,再乘以该指针的定义类型大小。举例子:一个三维 int 数组如下:
int arr[5][4][3];
那么指向 arr 的指针应该如下定义:
// 定义像个二维数组指针,其实是三维数组指针
int (*parr)[4][3];
parr = arr;
printf(" parr 地址:%p \n,", parr);
parr++
printf(" parr++ 地址:%p, 偏移量:%ld \n", parr, (long)parr-(long)arr);
输出:
由上图所示:偏移量为,最后一维3 * 第二维4 * sizeof(int) = 48。
令人厌烦的 ** 指针
char **p 这样定义的指针,就是双重指针,也就是指向指针的指针。双重指针主要的作用就是改变指针本身。也就是改变指针存放的地址值。例子:
printf(" \n ");
char *a;
a = 100;
printf("a 的值: %d \n", a);
char **p = &a;
*p = 200;
printf(" a 的值: %d \n", a);
char *c = "ccc";
printf(" c 指向的字符串: %s \n", c);
p = &c;
*p = "bbb";
printf(" c 所指向的字符串: %s \n", c);
输出:
指针指向普通变量,是用于读写变量的值,指针指向指针,也是一样原理,用于读写指针里面的地址值。
完
以上就是个人对指针的肤浅解读,希望对各位读者有所启发。欢迎大家评论转发。