“指针”一直以来都是初学者理解和掌握C语言的一大障碍,“指针”作为C语言的核心内容,如果不掌握指针的相关知识,就不能说是学会了C语言。
本文将通过文字描述+代码解析+图例展示的方式,详细解释C语言指针的含义,以期拨开指针之迷雾、得见C语言之精髓。
首先,“指针”是C语言定义的一种特殊的数据类型,众所周知,任何数据类型都要占用一定的内存空间,比如'char'类型占用一个字节内存、'short'占用2个字节内存等。指针作为一种数据类型,也占用一定的内存空间:32位机器上占用4字节,64位机器上占用8字节(不讨论CPU、操作系统、编译器位数不同的情况~~)。
那么,指针的“特殊”又是指什么呢?
我们知道,当我们定义一个'int'类型的变量时,可以给这个变量赋值不同的数值,当使用这个变量时,直接使用变量名即可。
但是,对于指针的操作,则必须通过两个特殊的运算符:‘&’—取地址运算符和‘*’—间接寻址运算符。
这也就是指针特殊的地方,指针本身占用的那块内存里面,存放的是另外一块内存空间的地址,我们不能直接使用指针的内容。
当给指针赋值的时候,需要使用‘&’运算符获取另外一个变量的内存地址——这也正说明了指针占用的内存空间的大小是和机器的位数(内存地址长度)相关的。
当通过指针访问它所指向那块内存的内容时,需要使用‘*’运算符间接获取另外一块内存空间中的内容。
而这个时候,就需要说到指针所指向的那块内存(另外一个变量)的数据类型了,也就是我们常说的“指针类型”,这个决定了我们通过'*'运算符所能够获取的内容大小。
也就是说,通过‘*’运算符操作一个指针变量时,编译器所能读取的内存大小、以及如何解析这块内存的内容。
有了上面的文字描述之后,我们再通过一段代码,详细解析一下指针变量、指针指向的变量的内容。
#include int main(void) {
printf("--------------------------------------------------------\n");
unsigned char uc[4] = {0x12, 0x34, 0x56, 0x78};
int index = 0;
for (;
index < 4;
index++) {
printf("uc[%d] = %#x, &uc[%d] = %p\n", index, uc[index], index, &(uc[index]));
}
printf("&index = %p\n", &index);
printf("--------------------------------------------------------\n");
unsigned char *puc = (unsigned char *)(&uc);
unsigned short *pus = (unsigned short *)(&uc);
printf("*puc = %#x,puc = %p, &puc = %p\n", *puc, puc, &puc);
printf("*pus = %#x, pus = %p, &pus = %p\n", *pus, pus, &pus);
printf("*(puc + 1) = %#x,(puc + 1) = %p\n", *(puc + 1), (puc + 1));
printf("*(pus + 1) = %#x, (pus + 1) = %p\n", *(pus + 1), (pus + 1));
printf("--------------------------------------------------------\n");
return 0;
}
上面代码的输出如下(每次执行后的内存地址会有变化):
文章图片
从上面的输出结果可以看出:
- puc和pus的内容即uc[0]的地址;
- puc和pus本身各自占用一块单独的内存空间;
- 通过‘*’运算符获取的puc和pus的内容,取决于puc和pus的“指针类型”;
- 对于指针加/减操作的步长,取决于”指针类型”。
文章图片
进而,根据上面‘*pus’的输出可以看出我使用的机器是小端的,再加上我的64位机器的指针占用8字节内存,可以进一步推导出如下的详细内存布局图:
文章图片
程序员在脑海中有了指针相关的内存布局图,再进一步理解那些更复杂一些的指针概念就不难了,比如:“指针的指针”、“指针数组”、“函数指针”~~
文章图片
文章图片
文章图片
【指针那些事儿~~】以上就是我对指针哪些事儿的理解,欢迎讨论、指导。
推荐阅读
- C|内存管理那些事儿_指针参数是如何传递内存的?
- 麦克算法|4指针与队列
- C|模拟实现memcpy函数(内存拷贝函数)
- javaweb|用quartz开发调度任无法注入bean,出现空指针问题
- 指针|C语言指针经典算法应用《指针作为函数参数》
- 算法学习笔记|【算法学习笔记】20.算法设计初步 归并排序 求逆序数
- Golang|golang 拷贝大切片一定比小切片代价大吗