指针是C语言的灵魂,我想对于一级指针大家应该都很熟悉,也经常用到:比如说对于字符串的处理,函数参数的“值,结果传递”等,对于二级指针或者多级指针,我想理解起来也是比较容易的,比如二级指针就是指向指针的指针.....n级指针就是....

 p    *p   **p
                                      ---  ---  ----
                                      | |->| |->|  |
                                      ---  ---  |  |
                                                |  |
                                                ----

  

但是可能大家比较不容易理解的是,二级指针或者多级指针用在哪里呢?怎么使用呢?有没有必要用呢?

现在我就谈谈C指针的比较经常用到的地方:

我们都知道C语言中函数传递参数都是传递"值"的,如下:

void fun(void)
{
int tmp = 0;
change(tmp);
printf("################ tmp = %d /n");
return ;
} void change(int tmp_t)
{
tmp_t =1;
return;
} 

这个时候fun()中打印出来的tmp值还是0,因为我们传递的是“值”,如果你想在函数change()中修改这个tmp的值能在fun()中生效的话,那么就需要用指针来传递了如下:

void fun(void)
{
int tmp = 0; change(&tmp); printf("################ tmp = %d /n"); return ;
} void change(int *tmp_t)
{
*tmp_t =1; return;
}

这个时候fun()中打印出来的tmp值就是1了,因为我们此时传进来的是tmp的地址,所以我们在change()中tmp_t就是tmp的地址了,而对于*tmp_t的操作其实就是对tmp的操作了。

到这里的时候我们可以试想一下,我们通过传递指针来达到修改一个值的目的,那么当你需要修改一个指针的时候呢,这个时候我们就需要指针的指针了,如下:

int fun(void)
{
int *buf ; int ret ; ret = mem_init(&buf); return ret;
} int mem_init(int **buf_t)
{
*buf_t = malloc(100); return 1;
}  

通过上面我们可以发现,fun()函数通过调用men_init()函数来实现给buf分配内存空间的目的。首先buf是我们定义的一个指针,&buf则是指向buf的指针(二级指针),我们通过把&buf传递个men_init()函数,那么此时二级指针buf_t=&buf了,所以说buf_t是指向buf的指针,那么对于*buf_t的操作其实就是对buf的操作了,这样fun()就可以通过men_init()来分配内存了。

补充一点:对于定义的int **buf_t中,二级指针buf_t=&buf,指向为buf(还是一个指针),一级指针*buf_t=buf,指向为*buf,值**buf_t= *buf。

对于n级指针的使用也是差不多这样了,这是本人的一点理解,如果有不对,希望大家多多指导。

易混淆的点


虽然修改一个指针指向的地址需要二级指针,但是这不等于我们修改一个指针指向的目标的值时也需要二级指针,因为 C 语言中有解引用符的存在。比如当我们只需要修改一个指针中的 val 或 next 字段时,可以直接使用 node->val = new_val 。

运用实例


  例一:声明一个结构体类型

typedef struct node
{ }TreeNode,*Tree;

  在main函数中我们定义一个Tree型的变量t,记Tree=t;

  现在声明一个Create函数,目的是创建一棵树,显然,这需要传入地址进行操作,那么参数应该设定为什么呢?

  由这篇文章我们知道,当我们通过传递指针来修改值,当我们需要修改的是指针时,那么就需要通过传递指针的指针进行修改了,

正确代码如下:     

Void Create(Tree *t);

int main()
{
Tree t;
Create(&t);
return 0;
}

  

  例二:判断int main()的形参列表(int argc,char **argv)

  相关代码:

//假设传递给程序的选项为 prog -d -o ofile data0

int main(int argc,char **argv)
{
for(int x=0 ; x<=5 ; x++)
cout << argv[x] << " "; //输出:程序名字 prog -d -o ofile data0
return 0; } 

  我们知道,数组名等于一级指针,那么传入的是名为argv的二级指针,可以认为传入的是指向char*类型的指针数组,内容存储的是指向字符串(char *)的指针,所以argv[x]表示的是在从argv位置起第X+1个字符串(argv[0]为第一个字符串)。

  通过这个原理,将代码改成如下形式也是可以的:

//假设传递给程序的选项为 prog -d -o ofile data0

int main(int argc,char **argv)
{
for(int x=0 ; x<=5 ; x++)
cout << *argv++ << " "; //输出:程序名字 prog -d -o ofile data0
return 0;
}

参考资料


《真正理解二级指针》:https://blog.csdn.net/liaoxinmeng/article/details/5811097

《二级指针作用详解》:https://zhuanlan.zhihu.com/p/89481530

C 真正理解二级指针的更多相关文章

  1. 深入理解C语言-二级指针三种内存模型

    二级指针相对于一级指针,显得更难,难在于指针和数组的混合,定义不同类型的二级指针,在使用的时候有着很大的区别 第一种内存模型char *arr[] 若有如下定义 char *arr[] = {&quo ...

  2. 【C】二级指针探秘 & 星号的两种用法(1.与基本类型结合形成另一种类型,比如与int结合形成int* 2.取值操作)

    1)问题:二级指针到底是什么?怎么用的?怎么存放的? #include <stdio.h> #define TEST_ADDR 0x12FF40 void main() { int a = ...

  3. C语言 二级指针内存模型混合实战

    //二级指针内存模型混合实战 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #i ...

  4. Linus:利用二级指针删除单向链表

    Linus大神在slashdot上回答一些编程爱好者的提问,其中一个人问他什么样的代码是他所喜好的,大婶表述了自己一些观点之后,举了一个指针的例子,解释了什么才是core low-level codi ...

  5. 【转】Linus:利用二级指针删除单向链表

    原文作者:陈皓 原文链接:http://coolshell.cn/articles/8990.html 感谢网友full_of_bull投递此文(注:此文最初发表在这个这里,我对原文后半段修改了许多, ...

  6. C#中调用C++的dll的参数为指针类型的导出函数(包括二级指针的情况)

    严格来说这篇文章算不上C++范围的,不过还是挂了点边,还是在自己的blog中记录一下吧. C++中使用指针是家常便饭了,也非常的好用,这也是我之所以喜欢C++的原因之一.但是在C#中就强调托管的概念了 ...

  7. 真正明白C语言二级指针(转载)

    指针是C语言的灵魂,我想对于一级指针大家应该都很熟悉,也经常用到:比如说对于字符串的处理,函数参数的“值,结果传递”等,对于二级指针或者多级指针,我想理解起来也是比较容易的,比如二级指针就是指向指针的 ...

  8. 转:Linus:利用二级指针删除单向链表

    感谢网友full_of_bull投递此文(注:此文最初发表在这个这里,我对原文后半段修改了许多,并加入了插图) Linus大婶在slashdot上回答一些编程爱好者的提问,其中一个人问他什么样的代码是 ...

  9. [C]二级指针

    二级指针即“指向指针的指针”: 下面的实例代码创建了一个二级指针c int a = 5; int* b = &a; int** c = &b; 你不能这样 int a = 5; int ...

随机推荐

  1. python 标准模块 string

    string 模块提供了一些用于处理字符串类型的函数 案例: #!/usr/bin/evn python #_*_ coding:utf-8 -*- import string text = &quo ...

  2. Chrome 浏览器报 filed to load resource:net err cache read failure 错误:

    在IE/FF下没有该错误提示,但在Chrome下命令行出现如下错误信息: Failed to load resource: net::ERR_CACHE_MISS 该问题是Chrome浏览器开发工具的 ...

  3. Python——正则表达式

    此篇文章结合小甲鱼的笔记和视频整理. 1 编译 Python 通过 re 模块为正则表达式引擎提供一个接口,同时允许你将正则表达式编译成模式对象,并用它们来进行匹配. 正则表达式被编译为模式对象,该对 ...

  4. 微信公众号 Cookie

    微信公众号开发中,使用cookie和session来存储用户状态. 但总会出现一些空的连接,cookie为[],访问路径为"\" 拦截请求输出为header为: ;Connecti ...

  5. 4.2 例题: 统计字符数 poj2247

    问题描述 判断一个由 a-z 这 26 个字符组成的字符串中哪个字符出现的次数最多 输入:第 1 行是测试数据的组数 n,每组测试数据占 1 行,是一个由 a-z 这 26 个字符组 成的字符串,每组 ...

  6. 「JavaScript」手起刀落-一起来写经典的贪吃蛇游戏

    回味 小时候玩的经典贪吃蛇游戏我们印象仍然深刻,谋划了几天,小时候喜欢玩的游戏,长大了终于有能力把他做出来(从来都没有通关过,不知道自己写的程序,是不是能通关了...),好了,闲话不多谈,先来看一下效 ...

  7. python中使用selenium调用Firefox缺少geckodriver解决方法

    from selenium import webdriver driver=webdriver.Firefox() 会报错 解决方法: 因为缺少geckodriver.exe,先到https://gi ...

  8. scrapy初试水 day03(递归调用)

    import scrapyfrom scrapy.http import Requestfrom scrapy.spider import Rulefrom scrapy.linkextractors ...

  9. zanphp 初探----安装篇

    安装 zanphp 的安装详细步骤具体在 http://zanphpdoc.zanphp.io/,但是安装的时候,还是踩了一些坑,Mac 和 Ubuntu 我都安装过, 分享大家注意一下. PHP 版 ...

  10. NOI导刊2010提高装备运输

    www.luogu.org/problem/show?pid=1794 挺裸的一题背包,算很基础. 可以运用的技巧是三维->二维(节省空间还能少敲一点代码 #include<iostrea ...