C指针:8 个关于指针的用法

资讯 3年前
680

一、前言

二、八个示例

   1. 修改主调函数中的数据

   2. 在被调用函数中,分配系统资源

   3. 传递函数指针

   4. 指向结构体的指针

   5. 函数指针数组

   6. 柔性数组

   7. 通过指针来获取结构体中成员变量的偏移量( offsetof 宏定义)

   8. 通过结构体中成员变量的指针,来获取该结构体的指针(container_of 宏定义)

三、总结

一、前言

半个月前写的那篇关于指针最底层原理的文章,得到了很多朋友的认可(链接: C语言指针-从底层原理到花式技巧,用图文和代码帮你讲解透彻),特别是对刚学习C语言的小伙伴来说,很容易就从根本上理解指针到底是什么、怎么用,这也让我坚信一句话;用心写出的文章,一定会被读者感受到!在写这篇文章的时候,我列了一个提纲,写到后面的时候,发现已经超过一万字了,但是提纲上还有最后一个主题没有写。如果继续写下去,文章体积就太大了,于是就留下了一个尾巴。

今天,我就把这个尾巴给补上去:主要是介绍指针在应用程序的编程中,经常使用的技巧。如果之前的那篇文章勉强算是“道”层面的话,那这篇文章就属于“术”的层面。主要通过 8 个示例程序来展示在 C 语言应用程序中,关于指针使用的常见套路,希望能给你带来收获。

记得我在校园里学习C语言的时候,南师大的黄凤良老师花了大半节课的时间给我们解释指针,现在最清楚地记得老师说过的一句话就是:指针就是地址,地址就是指针!

二、八个示例 

1. 开胃菜:修改主调函数中的数据// 交换 2 个 int 型数据void demo1_swap_data(int *a, int *b){    int tmp = *a;    *a = *b;    *b = tmp;}
void demo1(){    int i = 1;    int j = 2;    printf("before: i = %d, j = %d ", i, j);    demo1_swap_data(&i, &j);    printf("after:  i = %d, j = %d ", i, j);}

这个代码不用解释了,大家一看就明白。如果再过多解释的话,好像在侮辱智商。

2. 在被调用函数中,分配系统资源

代码的目的是:在被调用函数中,从堆区分配 size 个字节的空间,返回给主调函数中的 pData 指针。

void demo2_malloc_heap_error(char *buf, int size){    buf = (char *)malloc(size);    printf("buf = 0x%x ", buf);}
void demo2_malloc_heap_ok(char **buf, int size){    *buf = (char *)malloc(size);    printf("*buf = 0x%x ", *buf);}
void demo2(){    int size = 1024;    char *pData = NULL;
   // 错误用法    demo2_malloc_heap_error(pData, size);    printf("&pData = 0x%x, pData = 0x%x ", &pData, pData);
   // 正确用法    demo2_malloc_heap_ok(&pData, size);    printf("&pData = 0x%x, pData = 0x%x ", &pData, pData);    free(pData);}2.1 错误用法

刚进入被调用函数 demo2_malloc_heap_error 的时候,形参 buff 是一个 char* 型指针,它的值等于 pData 变量的值,也就是说 buff 与 pData 的值相同(都为 NULL),内存模型如图:

在被调用函数中执行 malloc 语句之后,从堆区申请得到的地址空间赋值给 buf,就是说它就指向了这个新的地址空间,而 pData 里仍然是NULL,内存模型如下:

从图中可以看到,pData 的内存中一直是 NULL,没有指向任何堆空间。另外,由于形参 buf 是放在函数的栈区的,从被调函数中返回的时候,堆区这块申请的空间就被泄漏了。

2.2 正确用法

刚进入被调用函数 demo2_malloc_heap_error 的时候,形参 buf 是一个 char* 型的二级指针,就是说 buf 里的值是另一个指针变量的地址,在这个示例中 buf 里的值就是 pData 这个指针变量的地址,内存模型如下:

在被调用函数中执行 malloc 语句之后,从堆区申请得到的地址空间赋值给 *buf,因为 buf = &pData,所以 *buf 就相当于是 pData,那么从堆区申请得到的地址空间就赋值 pData 变量,内存模型如下:

从被调函数中返回之后,pData 就正确的得到了一块堆空间,别忘了使用之后要主动释放。

© 版权声明

相关文章