c语言中如何通过二级指针来操作二维数组

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c语言中如何通过二级指针来操作二维数组相关的知识,希望对你有一定的参考价值。

1、首先我们打开电脑里的C语言软件,新建一个工程和.c文件,输入头文件和主函数。

2、然后我们输入图示代码初始化数组,定义变量类型。

3、然后我们输入图示代码用for语句实现数组的访问。

4、然后我们输入图示代码进行输出。

5、然后我们输入图示代码编译、运行,即可通过二级指针来操作二维数组。

参考技术A

通过二级指针去访问二维数组需要先给二级指针分配等同于二维数组行数的一维数组指针,然后把二维数组的每行首地址赋值给对应位置的一维指针上。之后就可以通过二维指针直接访问了。

参考代码如下,可以看具体注释辅助理解。

#include <stdio.h>//输入输出头文件。
#include <stdlib.h>//本程序需要用到malloc/free函数,引用该头文件。
int main()

    int a[3][4] = 1,2,3,4,5,6,7,8,9,10,11,12; //定义二维数组a,并赋值从1-12.
    int ** p = NULL;//定义二维指针。
    int i, j;
    
    p = (int **)malloc(sizeof(int *) *3);//要访问的数组有三行,所以申请三个一维指针变量。
    for(i = 0; i < 3; i ++)
    
        p[i] = a[i];//将二维数组行地址赋值到对应的一维指针上。
    
    
    for(i = 0; i < 3; i ++)
    
        for(j = 0; j < 4; j ++)
            printf("%d ", p[i][j]); //用指针输出元素。p[i][j]这里也可以写作*(*(p+i) + j)。
        printf("\\n"); //每行输出后加一个换行
    
    
    free(p);//释放申请的内存。
    
    return 0;

用二维指针访问二维数组多用于函数调用。

对于一维数组,如果函数参数为一维指针可以直接用数组名当做函数参数。但是如果函数参数为二维指针,直接用二维数组名做参数会出现访问出错,是因为二维指针和二维数组的访问方式不同造成的,需要如示例代码中做转换。

另外一种常用的方法是利用二维数组的内存连续性将二维数组转为一维数组处理,与本题无关,不做更多描述。

参考技术B 倘若此时有一个二级指针文件中可以编译通过,但会给出警告。若是在.CPP文件中则不会编译通过!我相信很多人的第一反应是加上强制类型转换:q=(int**)a;如此以来,程序编译、链接畅通无阻,连警告也没有!但一运行就会出问题:这是当然的!下面进行详细分析。。。。。。根据我上面讲述的:q可视为int**类型,且是int*变量的地址类型变量!对q (指针变量)的引用,得到是的其(即q)内存单元的数据,即int*变量的地址,*q则是获取q所指向的int*变量类型地址的内容,相当于int* Q变量Q的直接引用,得到是int类型变量的地址。q所占的内存为4BYTE,*q所占的内存也为4BYTE。一切都清楚了。现在来分析二维数组a的数据类型。我们知道指针与数组的联系的常见具体应用有两种:一种是“数组指针”:形如(*ptr)[];另外一种是“指针数组”:形如*ptr[]。两者之间的区别想必大家都清楚。如果我定义一个:“数组指针”并初始化:int (*pp)[3]=a;那么通过pp完全可以操作a[2][3]。来分析一下“数组指针”(*ptr)[SIZE],ptr所指的对象是有SIZE个某种数据类型值的数组。而ptr本身又是一级指针,一级指针又等价于一维数组。a[2][3]的低维是一个维度为3的一维数组。高维是一个维度为2的一维数组,不难理解,正如前面所述:二维数组的每个元素是一个一维数组,相当于一维数组的两次嵌套。比如变量a[0]是一个维度为3的一维数组,a[1]亦是一样。这样一来,高维的那一部分可视为一个指针!一个胆大的设想出来了:二维数组本质上就等同于“数组指针”!<typeinfo)cout<<typeid(a).name()<<endl;cout<<typeid(pp).name()<<endl;输出结果为:int (*)[3](换行)int (*)[3]两者完全相同,与设想一致!现在回到问题上来,q=(int**)a;强制转换成功,但却不可能正确运行!原因已浮出水面:q这个地址单元存放的是int*类型的“指针变量”的地址,而二维数组a骨子里却是一个“数组指针”。两者完全是“八竿子打不着”!想一想它们的内存分布情况,前者(地址)所指向的内存大小恒为4BYTE,后者(地址)所指向的内存大小是随着你定义的数组维数而不断变化的!即使通过强制类型转换成功,q的内存值就是a所代表的地址,但这个地址仅仅是一个地址,而q的内存值不仅要求是一个地址,而且还必须是一个“指针变量”的地址!只有这样通过*q(前面说过:*q则是获取q所指向的int*变量类型地址的内容,即一个int变量的地址)才能操作一个普通变量的地址,否则就是用“*”来操作普通变量,想一下int x=250;*x又是“数组指针”?这里有必要强调一下:我是从它们的存储映象上来讲的,但编译器的语义实现上两者是绝不能划等号的!你能够将一个二维数组赋值给一个一维数组吗?显然是不行的!因此我们这样想:语句q=(int**)a;是将一个一维数组(等价于一级指针)赋给一个二级指针(要通过“&”赋一级指针的地址才行),地球人都知道这是行不通的!虽然乍听起来还蛮合理的,其实此般理解无异于穿凿附会。刚才解释过,两者的语义迥异!不过,这样理解似乎更能深刻且方便地知道那样做错在哪里了,呵呵。本回答被提问者采纳

C 语言二级指针作为输入 ( 二维数组 | 二维数组内存大小计算 | 指针跳转步长问题 )





一、二维数组内存大小计算



给定一个二维数组 : 该 二维数组 中有 4 4 4 个 一维数组 , 每个一维数组有 10 10 10char 数据 ;

    // I. 二维数组
    char array[4][10] = "abc", "123", "258", "sfd";

计算二维数组大小 : 40 40 40 字节 ;

    // 求二维数组总的内存大小
    int array_len = sizeof(array);

计算一维数组大小 : 该 二维数组 中有 4 4 4 个 一维数组 , 每个一维数组有 10 10 10 字节 ;

    // 求二维数组中的一位数组的内存大小
    int array_0_len = sizeof(array[0]);

计算二维数组中有多少个一维数组 : 4 4 4 个 ;

    // 求二维数组中一维数组个数
    int len = sizeof(array) / sizeof(array[0]);

代码示例 :

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()

    // 循环控制变量
    int i = 0, j = 0;
    // 二维数组中的一维数组个数
    int num = 4;

    // 排序时 , 交换指针变量时的临时变量 , 存储指针指向的内存所存储的数据
    char tmp[10];

    // I. 二维数组
    char array[4][10] = "abc", "123", "258", "sfd";

    // 求二维数组总的内存大小
    int array_len = sizeof(array);

    // 求二维数组中的一位数组的内存大小
    int array_0_len = sizeof(array[0]);

    // 求二维数组中一维数组个数
    int len = sizeof(array) / sizeof(array[0]);

    // 打印上述大小
    printf("array_len = %d, array_0_len = %d, len = %d\\n", array_len, array_0_len, len);

    // 命令行不要退出
    system("pause");
    return 0;


执行结果 :





二、二维数组内存大小意义



编译器操作 二维数组 时 , 只关心 二维数组 的整体内存结构 , 下面的二维数组 有 4 4 4 10 10 10 列 ;

    // I. 二维数组
    char array[4][10] = "abc", "123", "258", "sfd";

当使用数组下标进行遍历时 ,

array[2]

相当于

*(array + 2)

由此可以看出 , array 的每个 跳转步长 是 10 10 10 字节 , array + 2 相当于跳了 20 20 20 字节 , 才能访问到第 3 3 3 个元素 array[2] ;


正是由于 上述 跳转步长 的问题 , 在函数中 , 形参 必须是 二维数组 , 不能是 二维指针 ;

/*
 * 此处遍历时 , 注意指针的步长 ,
 * 传入一个二级指针 char ** , 会出错
 * 如果传入 二级指针 ,
 * array[i] 等同于 *(array + i)
 * array 的步长是 10
 */
int print_str(char array[4][10], int num)

    // 循环控制变量
    int i = 0;

    // 判断指针合法性
    if(array == NULL)
    
        printf("array == NULL\\n");
        return -1;
    

    // 打印二维数组中的字符串
    for(i = 0; i < num; i++)
    
        // 使用数组下标形式访问
        printf("%s\\n", array[i]);
        // 使用指针访问
        //printf("%s\\n", *(array + i));
    

    return 0;

以上是关于c语言中如何通过二级指针来操作二维数组的主要内容,如果未能解决你的问题,请参考以下文章

c++二维数组和二级指针

C 语言二级指针作为输入 ( 二维数组 | 二维数组遍历 | 二维数组排序 )

C语言中的二维数组名是一个二重指针吗?

C 语言二级指针作为输入 ( 二维数组 | 抽象业务函数 | 二维数组打印函数 | 二维数组排序函数 )

C 语言二级指针内存模型 ( 指针数组 | 二维数组 | 自定义二级指针 | 将 一二 模型数据拷贝到 三 模型中 并 排序 )

C 语言二级指针 内存模型图 ( 指针数组 | 二维数组 | 自定义二级指针内存 )