精华内容
下载资源
问答
  • 本文主要介绍C语言 二级指针,这里整理了C语言二级指针的基础资料并附有示例代码和实现结果,帮助大家学习理解相关知识,有学习的朋友可以参考下
  • 转载:http://c.biancheng.net/cpp/html/85.html...如果一个指针指向的是另外一个指针,我们就称它为二级指针,或者指向指针的指针。假设有一个 int 类型的变量 a,p1是指向 a 的指针变量,p2 又是指向 p...

    转载:http://c.biancheng.net/cpp/html/85.html

    指针可以指向一份普通类型的数据,例如 int、double、char 等,也可以指向一份指针类型的数据,例如 int *、double *、char * 等。

    如果一个指针指向的是另外一个指针,我们就称它为二级指针,或者指向指针的指针。

    假设有一个 int 类型的变量 a,p1是指向 a 的指针变量,p2 又是指向 p1 的指针变量,它们的关系如下图所示:

    b92f0244642d00becdcaaab5605bd405.png

    将这种关系转换为C语言代码:

    int a =;

    int *p1 = &a;

    int **p2 = &p1;

    指针变量也是一种变量,也会占用存储空间,也可以使用&获取它的地址。C语言不限制指针的级数,每增加一级指针,在定义指针变量时就得增加一个星号*。p1 是一级指针,指向普通类型的数据,定义时有一个*;p2 是二级指针,指向一级指针 p1,定义时有两个*。

    如果我们希望再定义一个三级指针 p3,让它指向 p2,那么可以这样写:

    int ***p3 = &p2;

    四级指针也是类似的道理:

    int ****p4 = &p3;

    实际开发中会经常使用一级指针和二级指针,几乎用不到高级指针。

    想要获取指针指向的数据时,一级指针加一个*,二级指针加两个*,三级指针加三个*,以此类推,请看代码:

    #include

    int main(){

    int a =;

    int *p1 = &a;

    int **p2 = &p1;

    int ***p3 = &p2;

    printf("%d, %d, %d, %d\n", a, *p1, **p2, ***p3);

    printf("&p2 = %#X, p3 = %#X\n", &p2, p3);

    printf("&p1 = %#X, p2 = %#X, *p3 = %#X\n", &p1, p2, *p3);

    printf(" &a = %#X, p1 = %#X, *p2 = %#X, **p3 = %#X\n", &a, p1, *p2, **p3);

    return ;

    }

    运行结果:

    100, 100, 100, 100

    &p2 = 0X28FF3C, p3 = 0X28FF3C

    &p1 = 0X28FF40, p2 = 0X28FF40, *p3 = 0X28FF40

    &a = 0X28FF44, p1 = 0X28FF44, *p2 = 0X28FF44, **p3 = 0X28FF44

    以三级指针 p3 为例来分析上面的代码。***p3等价于*(*(*p3))。*p3 得到的是 p2 的值,也即 p1 的地址;*(*p3) 得到的是 p1 的值,也即 a 的地址;经过三次“取值”操作后,*(*(*p3)) 得到的才是 a 的值。

    假设 a、p1、p2、p3 的地址分别是 0X00A0、0X1000、0X2000、0X3000,它们之间的关系可以用下图来描述:

    200a79c6bbd8264e7877d725a2bf0496.png

    方框里面是变量本身的值,方框下面是变量的地址。

    C 指针常量 和常量指针 指向常量的指针常量的使用

    #include /* 指针常量 和常量指针 指向常量的指针常量 */ int main() { int a = 100; int b =200; int* const ...

    指针常量&常量指针&指向常量的指针常量

    搞不懂不吃晚饭 (1)指针常量 指针常量是一个常量,但是是指针修饰的. 格式:int * const p; 例如 int a, b; int * const p = &a;//指针常量 //分 ...

    C语言的本质(10)——指针本质

    指针,大概是C语言中最难理解的概念之一了.指针这个东西是C语言中的一个基本概念,C99中对于指针的定义是: 1. 指针的类型是derived from其它类型,也就是说指针的类型是由它指向的类型决定的 ...

    C语言语法笔记 – 高级用法 指针数组 指针的指针 二维数组指针 结构体指针 链表 | IT宅.com

    原文:C语言语法笔记 – 高级用法 指针数组 指针的指针 二维数组指针 结构体指针 链表 | IT宅.com C语言语法笔记 – 高级用法 指针数组 指针的指针 二维数组指针 结构体指针 链表 | I ...

    C语言的本质(12)——指针与函数

    往往,我们一提到指针函数和函数指针的时候,就有很多人弄不懂.下面详细为大家介绍C语言中指针函数和函数指针. 1.指针函数 当一个函数声明其返回值为一个指针时,实际上就是返回一个地址给调用函数,以用于需 ...

    C++指向常量的指针和常指针

    C++指向常量的指针和常指针 指向常量的指针 通常情况下,可以通过指针去修改指针指向的内容.但是在某些情况下,只希望通过指针去访问指针指向的内容,不想修改.比如只想通过树根结点的指针去遍历输出树中所有 ...

    C/C++语言中指针数组和数组指针比较区别

    指针数组:int *p[3] 定义一个指针数组,其中每个数组元素指向一个int型变量的地址 意思就是指针的数组,数组里面都是指针 例子: int *p[3];//定义了一个指针数组,有3个成员,每个成 ...

    指针总结指向const的指针、const指针、指向const指针的const指针

    指针的一些总结   const与指针 指向const的指针指的是指针指向的数据是常量,不可以被修改,但指针变量本身可以被修改,如const int *p:严格说不能用指针间接修改指向的数据,但该变量可 ...

    Const指针 、 指向const的指针 、引用、指针

    1. const指针和 指向const的指针 指向const的指针: 不允许通过指针来改变其指向的const值 const double *cptr *cptr = 42;  // error! 指针 ...

    随机推荐

    JAVA动手动脑

    1.运行 TestInherits.java 示例,观察输出,注意总结父类与子类之间构造方法的调用关系修改Parent构造方法的代码,显式调用GrandParent的另一个构造函数,注意这句调用代码是 ...

    PHP学习之常量

    1.常量是一个简单值的标识符,该值在脚本中不能改变: 2.一个常量由英文字母,下划线,和数字组成,但数字不能作为首字母出现:(常量名中不需要加$修饰符) 3.常量在整个脚本中都可以使用: 4.设置PH ...

    Node.js V0.12 新特性之性能优化

    v0.12悠长的开发周期(已经过去九个月了,并且还在继续,是有史以来最长的一次)让核心团队和贡献者们有充分的机会对性能做一些优化. 本文会介绍其中最值得注意的几个. http://www.infoq. ...

    Cloudera的安装

    To enable these parts of the tutorial, choose one of the following options: To use Cloudera Express ...

    构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(44)-工作流设计-设计表单

    原文:构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(44)-工作流设计-设计表单 系列目录 设计表单是比较复杂的一步,完成一个表单的设计其实很漫长,主要分为四 ...

    简单粗暴的上传项目至 Github

    嗯,写了一个项目,觉得还OK,就想放在 Github 继续维护和方便使用,那么如何简单快速的将代码上传至 Github 上? 1.  你得有自己的 Github账号,如何创建账号这里就不说了.因为.. ...

    react项目请求数据的fetch的使用

    准备三个文件(封装请求函数),然后测试一下,能不能调用数据 第一个文件  request.js import 'whatwg-fetch'; /** * Parses the JSON returne ...

    CRT && exCRT模板

    CRT从各种方面上都吊打exCRT啊...... 短,好理解... 考虑构造bi使得bi % pi = ai,bi % pj = 0.然后全加起来就行了. 显然bi的构造就是ai * (P/pi) * ...

    jenkins 使用的python 不是指定的python 的解决方法

    构建的时候加上要使用python的解析器路径 终端 which python 可以找到 python编辑器里面 import os os.system("which python" ...

    展开全文
  • c语言二级指针

    千次阅读 2018-12-13 09:51:41
    二级指针做输入_第1种内存模型 直接利用二级指针 首先看指针数组(变量为指针) 也就是数组中存的都是地址 #include<stdio.h> void main() { int i = 0, j = 0; int num = 0; char *myArray[] ...

    二级指针做输入_第1种内存模型 直接利用二级指针

    首先看指针数组(变量为指针) 也就是数组中存的都是地址

    #include<stdio.h>
    
    void main()
    {
        int i = 0, j = 0;
    	int num = 0;
    	char *myArray[] = {"aaaaaa","cccccc","bbbbbb","111111"};//这里定义的是指针所指向的内存
    
    	num = sizeof(myArray)/sizeof(myArray[0]);
    	for(i = 0;i < num;i++)
    	{
    	printf("1:%s\n",myArray[i]);
    	printf("2:%s\n",*(myArray+i));
    	}
    }

     两种输出结果一样说明指针数组储存的是指针

    #include<stdio.h>
    #include<string.h>
    
    void main()
    {
        int i = 0, j = 0;
    	int num = 0;
    	char *tmp;
    	char *myArray[] = {"aaaaaa","cccccc","bbbbbb","111111"};
    
    	num = sizeof(myArray)/sizeof(myArray[0]);
    
    	//利用冒泡原理进行排序
    	for(i = 0;i < num;i++)
    	{
    	    for(j = i;j < num;j++)
    		{
    			if(strcmp(myArray[i],myArray[j])>0)
    			{
    				tmp = myArray[i];
    				myArray[i] = myArray[j];
    				myArray[j] = tmp;
    			}
    		}
    	}
    	for(i = 0;i < num;i++)
    	{
    	    printf("%s\n",myArray[i]);
    	}
    }

    下面进行封装

    #include<stdio.h>
    #include<string.h>
    
    void printMyArray(char **myArray,int num);
    void sortMyArray(char **myArray,int num);
    
    void main()
    {
        
    	int num = 0;
    	char *myArray[] = {"aaaaaa","cccccc","bbbbbb","111111"};
    	num = sizeof(myArray)/sizeof(myArray[0]);
    	sortMyArray(myArray, num);
    	printMyArray(myArray, num);
    }
    
    void printMyArray(char **myArray,int num)
    {
        int i = 0;
    	for(i = 0;i < num;i++)
    	{
    	    printf("%s\n",myArray[i]);
    	}
    }
    
    void sortMyArray(char **myArray,int num)
    {
        int i = 0, j = 0;
    	char *tmp = NULL;
    	//利用冒泡原理进行排序
    	for(i = 0;i < num;i++)
    	{
    	    for(j = i;j < num;j++)
    		{
    			if(strcmp(myArray[i],myArray[j])>0)
    			{
    				tmp = myArray[i];
    				myArray[i] = myArray[j];
    				myArray[j] = tmp;
    			}
    		}
    	}
    }

    其实数组的名称退化为数组的首地址 放在指针数组同样会退化成指针的指针也就是二级指针

     

    二级指针做输入_第2种内存模型 利用二维数组

    二维数组指针表示,C语言指针引用二维数组详解

    首先了解一下二维数组的指针

    指针变量可以指向一维数组中的元素,当然也就可以指向二维数组中的元素。但是在概念和使用方法上,二维数组的指针比一维数组的指针要复杂一些。要理解指针和二维数组的关系首先要记住一句话:二维数组就是一维数组,这句话该怎么理解呢?

    假如有一个二维数组:

    1. int a[3][4] = {{1, 3, 5, 7}, {9, 11, 13, 15}, {17, 19, 21, 23}};

    其中,a 是二维数组名。a 数组包含 3 行,即 3 个行元素:a[0],a[1],a[2]。每个行元素都可以看成含有 4 个元素的一维数组。而且 C 语言规定,a[0]、a[1]、a[2]分别是这三个一维数组的数组名。如下所示:



    a[0]、a[1]、a[2] 既然是一维数组名,一维数组的数组名表示的就是数组第一个元素的地址,所以 a[0] 表示的就是元素 a[0][0] 的地址,即 a[0]==&a[0][0];a[1] 表示的就是元素 a[1][0] 的地址,即 a[1]==&a[1][0];a[2] 表示的就是元素 a[2][0] 的地址,即 a[2]==&a[2][0]。

    所以二维数组a[M][N]中,a[i]表示的就是元素a[i][0]的地址,即:

    a[i] == &a[i][0]                                                 

    我们知道,在一维数组 b 中,数组名 b 代表数组的首地址,即数组第一个元素的地址,b+1 代表数组第二个元素的地址,…,b+n 代表数组第 n+1 个元素的地址。所以既然 a[0]、a[1]、a[2]、…、a[M–1] 分别表示二维数组 a[M][N] 第 0 行、第 1 行、第 2 行、…、第 M–1 行各一维数组的首地址,那么同样的道理,a[0]+1 就表示元素 a[0][1] 的地址,a[0]+2 就表示元素 a[0][2] 的地址,a[1]+1 就表示元素 a[1][1] 的地址,a[1]+2 就表示元素 a[1][2] 的地址……a[i]+j 就表示 a[i][j] 的地址,即:

    a[i]+j == &a[i][j]

    将式一代入式二得:

    &a[i][0]+j == &a[i][j]

    在一维数组中 a[i] 和 *(a+i)  等价,即:

    a[i] == *(a+i)

    这个关系在二维数组中同样适用,二维数组 a[M][N] 就是有 M 个元素 a[0]、a[1]、…、a[M–1] 的一维数组。将式四代入式二得(式五)

    *(a+i)+j == &a[i][j]

    由式二和式五可知,a[i]+j 和 *(a+i)+j 等价,都表示元素 a[i][j] 的地址。

    上面几个公式很“绕”,理清楚了也很简单,关键是把式二和式五记住。

    二维数组的首地址和数组名

    下面来探讨一个问题:“二维数组 a[M][N] 的数组名 a 表示的是谁的地址?”在一维数组中,数组名表示的是数组第一个元素的地址,那么二维数组呢? a 表示的是元素 a[0][0] 的地址吗?不是!我们说过,二维数组就是一维数组,二维数组 a[3][4] 就是有三个元素 a[0]、a[1]、a[2] 的一维数组,所以数组 a 的第一个元素不是 a[0][0],而是 a[0],所以数组名 a 表示的不是元素 a[0][0] 的地址,而是 a[0] 的地址,即:

    a == &a[0]

    而 a[0] 又是 a[0][0] 的地址,即:

    a[0] == &a[0][0]

    所以二维数组名 a 和元素 a[0][0] 的关系是:

    a == &(&a[0][0])

    即二维数组名 a 是地址的地址,必须两次取值才可以取出数组中存储的数据。对于二维数组 a[M][N],数组名 a 的类型为 int(*)[N],所以如果定义了一个指针变量 p:

    int *p;

    并希望这个指针变量指向二维数组 a,那么不能把 a 赋给 p,因为它们的类型不一样。要么把 &a[0][0] 赋给 p,要么把 a[0] 赋给 p,要么把 *a 赋给 p。前两个好理解,可为什么可以把 *a 赋给 p?因为 a==&(&a[0][0]),所以 *a==*(&(&a[0][0]))==&a[0][0]。

    除此之外你也可以把指针变量 p 定义成 int(*)[N] 型,这时就可以把 a 赋给 p,而且用这种方法的人还比较多,但我不喜欢,因为我觉得这样定义看起来很别扭。

    如果将二维数组名 a 赋给指针变量 p,则有:

    p == a

    那么此时如何用 p 指向元素 a[i][j]?答案是以“行”为单位进行访问。数组名 a 代表第一个元素 a[0] 的地址,则 a+1 就代表元素 a[1] 的地址,即a+1==&a[1];a+2 就代表 a[2] 的地址,即 a+2==&a[2]……a+i 就代表 a[i] 的地址,即(式七)

    a+i == &a[i]

    将式六代入式七得:

    p+i == &a[i]

    等式两边作“*”运算得:

    *(p+i) == a[i]

    等式两边同时加上j行:

    *(p+i) + j == &a[i][j]

    式八就是把二维数组名 a 赋给指针变量 p 时,p 访问二维数组元素的公式。使用时,必须先把 p 定义成 int(*)[N] 型,然后才能把二维数组名 a 赋给 p。那么怎么把 p 定义成 int(*)[N] 型呢?关键是 p 放什么位置!形式如下:

     
    1. int (*p)[N] = a; /*其中N是二维数组a[M][N]的列数, 是一个数字, 前面说过, 数组长度不能定义成变量*/

    下面编一个程序来用一下:

     
    1. # include <stdio.h>
    2. int main(void)
    3. {
    4. int a[3][4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
    5. int i, j;
    6. int (*p)[4] = a; //记住这种定义格式
    7. for (i=0; i<3; ++i)
    8. {
    9. for (j=0; j<4; ++j)
    10. {
    11. printf("%-2d\x20", *(*(p+i)+j)); /*%-2d中, '-'表示左对齐, 如果不写'-'则默认表示右对齐;2表示这个元素输出时占两个空格的空间*/
    12. }
    13. printf("\n");
    14. }
    15. return 0;
    16. }

    输出结果是:
    1  2  3  4
    5  6  7  8
    9  10 11 12

    如果把 &a[0][0] 赋给指针变量 p 的话,那么如何用 p 指向元素 a[i][j] 呢?在前面讲过,对于内存而言,并不存在多维数组,因为内存是一维的,内存里面不分行也不分列,元素都是按顺序一个一个往后排的,所以二维数组中的每一个元素在内存中的地址都是连续的,写一个程序来验证一下:

     
    1. # include <stdio.h>
    2. int main(void)
    3. {
    4. int a[3][4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
    5. int i, j;
    6. for (i=0; i<3; ++i)
    7. {
    8. for (j=0; j<4; ++j)
    9. {
    10. printf("%#X\x20", &a[i][j]);
    11. }
    12. printf("\n");
    13. }
    14. return 0;
    15. }

    输出结果是:
    0X18FF18 0X18FF1C 0X18FF20 0X18FF24
    0X18FF28 0X18FF2C 0X18FF30 0X18FF34
    0X18FF38 0X18FF3C 0X18FF40 0X18FF44

    我们看到地址都是连续的。所以对于数组 a[3][4],如果把 &a[0][0] 赋给指针变量 p 的话,那么:

     
    1. p == &a[0][0]; p + 1 == &a[0][1]; p + 2 == &a[0][2]; p + 3 == &a[0][3];
    2. p + 4 == &a[1][0]; p + 5 == &a[1][1]; p + 6 == &a[1][2]; p + 7 == &a[1][3];
    3. p + 8 == &a[2][0]; p + 9 == &a[2][1]; p + 10 == &a[2][2]; p + 10 == &a[2][3];

    如果仔细观察就会发现有如下规律:

    p+i*4+j == &a[i][j]

    其中 4 是二维数组的列数。

    所以对于二维数组 a[M][N],如果将 &a[0][0] 赋给指针变量 p 的话,那么 p 访问二维数组元素 a[i][j] 的公式就是:

    p + i*N +j == &a[i][j]

    下面把验证式八的程序修改一下,验证一下上式:

     
    1. # include <stdio.h>
    2. int main(void)
    3. {
    4. int a[3][4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
    5. int i, j;
    6. int *p = &a[0][0]; //把a[0][0]的地址赋给指针变量p
    7. for (i=0; i<3; ++i)
    8. {
    9. for (j=0; j<4; ++j)
    10. {
    11. printf("%-2d\x20", *(p+i*4+j));
    12. }
    13. printf("\n");
    14. }
    15. return 0;
    16. }

    输出结果是:
    1  2  3  4
    5  6  7  8
    9  10 11 12

    结果是一样的。两种方法相比,第二种方法更容易接受,因为把 &a[0][0] 赋给指针变量 p 理解起来更容易,而且 p 定义成 int* 型从心理上或从感觉上都更容易接受。

     以上转自 http://c.biancheng.net/view/227.html

    因此可以看出 利用二维数组同样可以达到二级指针的作用去对字符串操作

     

    二级指针做输入_第3种内存模型 开辟内存空间

    开辟内存空间存储二维指针从而形成二级指针数组

    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    
    void main()
    {
    char **p2 = NULL;
    int num = 5;
    int i,j;
    char *tmp = NULL;
    p2 = (char**)malloc(sizeof(char*)*num);
    
    for(i = 0; i < num; i++)
    {
        p2[i] = (char *)malloc(sizeof(char)*100);
    	sprintf(p2[i],"%d%d%d",i+1,i+1,i+1);
    }
    
    printf("排序之前:\n");
    for(i = 0;i < num; i++)
    {
        printf("%s\n",p2[i]);      
    }
    
    
    for(i = 0;i < num; i++)
    {
        for(j = i+1;j< num;j++)
    	{
    	    if(strcmp(p2[i],p2[j])<0);
    		{
    		    tmp = p2[i];
    			p2[i] = p2[j];
    			p2[j] = tmp;
    		}
    	}
    }
    
    printf("排序之后:\n");
    for(i = 0;i < num; i++)
    {
        printf("%s\n",p2[i]);      
    }
    
    //释放内存
    for(i = 0;i< num;i++)
    {
        if(p2[i] != NULL)
    	{
    	    free(p2[i]);
    		p2[i] = NULL;
    
    	}
    	if(p2[i]=NULL)
    	{
    	    free(p2[i]);
    	}
    }
    }

    现在我们在冒泡排序的时候交换的是指针 下面我们来交换内存块

    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    
    void main()
    {
    char **p2 = NULL;
    int num = 5;
    int i,j;
    char tmpbuf[100];
    p2 = (char**)malloc(sizeof(char*)*num);
    
    for(i = 0; i < num; i++)
    {
        p2[i] = (char *)malloc(sizeof(char)*100);
    	sprintf(p2[i],"%d%d%d",i+1,i+1,i+1);
    }
    
    printf("排序之前:\n");
    for(i = 0;i < num; i++)
    {
        printf("%s\n",p2[i]);      
    }
    
    
    for(i = 0;i < num; i++)
    {
        for(j = i+1;j< num;j++)
    	{
    	    if(strcmp(p2[i],p2[j])<0);
    		{
    		    strcpy(tmpbuf,p2[i]);
    			strcpy(p2[i],p2[j]);
    			strcpy(p2[j],tmpbuf);
    		}
    	}
    }
    
    printf("排序之后:\n");
    for(i = 0;i < num; i++)
    {
        printf("%s\n",p2[i]);      
    }
    
    //释放内存
    for(i = 0;i< num;i++)
    {
        if(p2[i] != NULL)
    	{
    	    free(p2[i]);
    		p2[i] = NULL;
    
    	}
    	if(p2[i]=NULL)
    	{
    	    free(p2[i]);
    	}
    }
    }

     下面进行封装

    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    
    char **getMem(int num);
    void printMyArray(char **myArray,int num);
    void sortMyArray(char **myArray,int num);
    void getMem_free(char **p2,int num);
    
    void main()
    {
    char **p2 = NULL;
    int num = 5;
    int i,j;
    char tmpbuf[100];
    p2 = getMem(num);
    
    printf("排序之前:\n");
    printMyArray(p2,num);
    
    
    sortMyArray(p2,num);
    
    printf("排序之后:\n");
    printMyArray(p2,num);
    
    getMem_free(p2,num);
    
    p2 = NULL;//将p2释放
    
    }
    
    char **getMem(int num)
    {
        int i;
    	char **p2;
    	p2 = (char**)malloc(sizeof(char *)*num);
    	if(p2 == NULL )
    	{
    	    return NULL;
    	}
    	for(i = 0;i < num;i++)
        {
            p2[i] = (char *)malloc(sizeof(char)*100);
    		sprintf(p2[i],"%d%d%d",i+1,i+1,i+1);
    	}
    	return p2;
    }
    
    void printMyArray(char **myArray,int num)
    {
        int i = 0;
    	for(i = 0;i < num;i++)
    	{
    	    printf("%s\n",myArray[i]);
    	}
    }
    
    void sortMyArray(char **myArray,int num)
    {
        int i = 0, j = 0;
    	char *tmp = NULL;
    	//利用冒泡原理进行排序
    	for(i = 0;i < num;i++)
    	{
    	    for(j = i;j < num;j++)
    		{
    			if(strcmp(myArray[i],myArray[j])>0)
    			{
    				tmp = myArray[i];
    				myArray[i] = myArray[j];
    				myArray[j] = tmp;
    			}
    		}
    	}
    }
    
    void getMem_free(char **p2,int num)
    {
    
    	int i = 0;
    	for(i = 0;i< num;i++)
    	{
            if(p2[i] != NULL)
    		{
    	        free(p2[i]);
    		    p2[i] = NULL;
    
    		}
    	    if(p2[i]=NULL)
    		{
    	        free(p2[i]);
    		}
    	}
    }
    

     

     

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

    指针是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=&

    amp;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语言二级指针与二维数组

    千次阅读 2019-04-09 21:25:59
      最近用C语言写LeetCode 有的题目给的函数把二维数组用二级指针传进来 并传入行数和列数 引起一些疑惑 本来以为C语言学得海星,查了一些资料后,觉得自己还是个弟弟 : ( 按一维数组的思路处理二维数组,将二维...

    前言

      最近用C语言写LeetCode 有的题目给的函数把二维数组用二级指针传进来 并传入行数和列数 引起一些疑惑

    本来以为C语言学得海星,查了一些资料后,觉得自己还是个弟弟 : (


    按一维数组的思路处理二维数组,将二维数组名作为二级指针传入
    在这里插入图片描述

    出现异常(图示运行在DEVC++中)

    在这里插入图片描述

    二维数组名+1相当于在行上+1
    然而传入的二级指针

    在这里插入图片描述

    按二维指针指针传入的num失去了二维数组的性质,相当于仅进行了数组首地址的传递,和一个普通的int *指针没有区别

    在这里插入图片描述
    仅进行了地址值的传递,甚至可凭借数组的连续性按一维数组的方式来访问元素



    那怎么传递二维数组呢?

    如果行列数已知,可以用如下方法
    在这里插入图片描述
    这里列下标是必填的,因为只有确定了列下标,程序才知道计算num[i]这种地址时该以多少个元素作为一行,由num+1的结果也可以看出num已经是正常的二维数组名了

    也可以用int (*num)[3],效果与int num[ ][3]等价
    int (*num)[3] 说明num是一个指向有三个int元素数组的指针,所以步长也为3 × sizeof(int),同用一维数组访问的方式类似



    那如何以指针形式进行访问呢?
    除了上面以一维数组的方式进行访问外,还可以将二维数组还原回来

    void test(int **num, int row, int col) {
    	int **p = (int **)malloc(sizeof(int *)*row);
    	或者int *p[2];//int *p[row];
    	for(int i = 0;i<row;i++){
    		p[i] = num+i*col;
    	}
    	printf("num[1][1] = %d\n", p[1][1]);//输出为4
    	free(p);
    }
    
    int main() {
    	int num[2][3]= {{0,1,2},{3,4,5}};
    	test(num,2,3);
    	return 0;
    }
    


    2019/04/09

    会再更新指针的博客的

    展开全文
  • c语言二级指针与二维数组

    千次阅读 2019-05-20 15:00:56
    一、二维数组的地址不能赋给二级指针的原因 int arr[][3] = { { 1,2,3 },{ 4,5,6 },{ 7,8,9 } }; int** p = arr; 二、指针遍历二维数组 int* p1 = arr; for (int i = 0; i < sizeof(arr)/sizeof(arr[0][0]); ...
  • 很多初学者都对C中的指针很迷糊,希望这篇blog能帮助到大家:1.什么是“指针”:在执行C程序的时候,由于我们的数据是存储在内存中的。所以对于C程序本身来说,如果想找到相应被调用的数据,就要知道存储该数据的...
  • 指针是C语言的灵魂,我想对于一级指针大家应该都很熟悉,也经常用到:比如说对于字符串的处理,函数参数的“值,结果传递”等,对于二级指针或者多级指针,我想理解起来也是比较容易的,比如二级指针就是指向指针的...
  • c语言二级指针开辟空间

    千次阅读 2019-05-28 09:13:53
    、代码 int** p = (int**)malloc(sizeof(int*)* 3);//p中存的地址是开辟的空间的首地址 for (int i = 0; i < 3;i++) { *(p + i) = (int*)malloc(sizeof(int) * 3);//p+i中存的地址是开辟的空间的首地址 } ...
  • c语言二级指针与指针数组

    千次阅读 2019-05-19 18:38:05
    一、代码 int main(int argc, const char * argv[]) { int a[] = {1,2,3}; int b[] = {4,5,6};... int c[] = {7,8,8}; int* arr[] = {a,b,c}; int** p = arr; printf("a[0] = %d\n",a[0]); ...
  • #include<stdio.h> #include<stdlib.h> void AllocateMemory(int **pGetMemory, int n) { int *p = (int*)malloc(sizeof(int) * n); if (p == NULL) { *pGetMemory = NULL;... ...
  • C语言二级指针的介绍和使用

    千次阅读 2017-02-24 16:02:58
    一、一级指针级指针的简单描述 ①一级指针是一种以存储其他变量地址为目的的变量。一个T类型的指针变量(一级指针)就是一个存储了某T类型值变量的内存地址的引用。 ②对指针的解引用(也就是*),是获取...
  • C语言二级指针在用到动态二维数组的时候经常用到,除此之外,我们还经常利用二级指针充当地址引用(比普通引用灵活很多可以自由赋值)来做一些意想不到的操作! 比如接下来要讲的链表的删除元素操作。我喜欢把指针...
  • 关于C语言二级指针正确使用总结

    千次阅读 2020-02-10 15:39:45
    关于C语言二级指针正确使用总结 什么是二级指针 C语言中的二级指针其实就是指向指针的指针,指向指针的指针是一种多级间接寻址的形式,或者说是一个指针链。同理可以构建三级或者N级指针,但是一般情况下用不到多级...
  • 二级指针相对于一级指针,显得更难,难在于指针和数组的混合,定义不同类型的二级指针,在使用的时候有着很大的区别第一种内存模型char *arr[]若有如下定义char *arr[] = {"abc", "def", "ghi"};这种模型为二级指针...
  • 如何通过二级指针间接赋值,首先举个例子: # define _CRT_SECURE_NO_WARNINGS # include <stdio.h> # include <stdlib.h> # include <string.h> void fun2(int * p) { p = 0xaabb; printf...
  • 指针的概念  指针就是地址, 利用这个地址可以找到指定的数据  指针就是地址, 那么在使用的时候, 常常会简单的说 指针变量为指针  指针变量就是存储地址的变量  int *p1;// 申请了一个变量, 即在内存中开辟了一块...
  • C语言——二级指针

    2021-07-15 04:38:23
    二级指针的概念首先任何值都有地址,一级指针的值虽然是地址,但这个地址做为一个值亦需要空间来存放,是空间就具有地址,这就是存放地址这一值的空间所具有的地址,二级指针就是为了获取这个地址,一级指针所关联的...
  • 而在更改链表时,看的书上一般都是传入二级指针,因为这时候改变了指针的指向。但实际上,只要不更改头指针,只传入一级指针就足够了。 #include<stdio.h> #include<stdlib.h> #define MAXSIZE 20 ...
  • 主要内容:1、一级指针和二级指针2、函数指针传递的例子3、什么时候需要传递二级指针?4、二级指针在链表中的使用1、一级指针和二级指针一级指针:即我们一般说的指针,就是内存地址;二级指针:指向指针的指针,...
  • C语言二级指针

    2019-10-05 17:39:37
    二级指针,表示p所指向的地址里面存放的是一个int类型的指针,即p所指向的地址里面是一个指向int的一级指针 例子 int i=3; 定义了一个int类型的变量 int *p=&i; 定义了一个指针指向这个整形...
  • C语言二级指针与典型应用(1)

    千次阅读 多人点赞 2018-03-25 16:44:30
    二级指针的定义:A(即B的地址)是指向指针的指针,称为二级指针,用于存放二级指针的变量称为二级指针变量.本质:二级指针变量的值是一个地址。一、概念在如下的A指向B、B指向C的指向关系中:首先,默认的编译器是32...
  • C语言 二级指针的定义与理解

    千次阅读 2019-06-26 18:23:27
    二级指针定义格式: 类型* 指针名; 例:int *p; 二级指针用于存储一级指针的内存地址。 二级指针赋值实例: int *p = &a; int* *pp = &p; 注意,只能同等类型赋值,不能不同类型赋值; 例如 char *p = &a...
  • 虽然有时我们说“二级指针”这个词,这可能在描述某些问题时较为方便,但你一定要记住:C 语言中只有指针,没有什么二级指针——或者说,所谓“二级指针”并不是什么特殊的东西,它就是指针(不过是指向指针的指针)。...
  • 指针的概念指针就是地址, 利用这个地址可以找到指定的数据指针就是地址, 那么在使用的时候, 常常会简单的说 指针变量为指针指针变量就是存储地址的变量int *p1;// 申请了一个变量, 即在内存中开辟了一块内存, 存储...
  • 1.用指针做函数参数申请动态内存的问题//如果函数参数是指针,不能用一级指针做函数参数实现申请动态内存void getMemory(char *p, int num){p = (char *)malloc(sizeof(char)*num);}void main(){char *str = NULL;...
  • 主要介绍了C语言二级指针的实例详解的相关资料,希望通过本文能帮助到大家,让大家掌握理解二级指针的知识,需要的朋友可以参考下
  • 使用二级指针创建单链表,程序功能菜单如图所示void showMenu(){ printf("\t\t\t\t\t\t1.使用头插法创建链表\n"); printf("\t\t\t\t\t\t2.使用尾插法创建链表\n"); printf("\t\t\t\t\t\t3.按序号查找\n"); ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 221,181
精华内容 88,472
关键字:

c二级指针