精华内容
下载资源
问答
  • C语言二维数组指针(指向二维数组的指针)详解

    千次阅读 多人点赞 2020-05-27 17:43:22
    如有需要,请访问C语言二维数组指针(指向二维数组的指针)详解 二维数组在概念上是二维的,有行和列,但在内存中所有的数组元素都是连续排列的,它们之间没有“缝隙”。以下面的二维数组 a 为例: int a[3][4] = { ...

    声明!本文转载仅为方便学习使用!
    如有需要,请访问
    C语言指针数组(数组每个元素都是指针)详解
    C语言二维数组指针(指向二维数组的指针)详解

    二维数组在概念上是二维的,有行和列,但在内存中所有的数组元素都是连续排列的,它们之间没有“缝隙”。以下面的二维数组 a 为例:

    int a[3][4] = { {0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11} };
    

    从概念上理解,a 的分布像一个矩阵:

    0   1   2   3
    4   5   6   7
    8   9  10  11
    

    但在内存中,a 的分布是一维线性的,整个数组占用一块连续的内存:
    二维数组在内存中的存储

    C语言中的二维数组是按行排列的,也就是先存放 a[0] 行,再存放 a[1] 行,最后存放 a[2] 行;每行中的 4 个元素也是依次存放。数组 a 为 int 类型,每个元素占用 4 个字节,整个数组共占用 4×(3×4) = 48 个字节。

    C语言允许把一个二维数组分解成多个一维数组来处理。对于数组 a,它可以分解成三个一维数组,即 a[0]、a[1]、a[2]。每一个一维数组又包含了 4 个元素,例如 a[0] 包含 a[0][0]、a[0][1]、a[0][2]、a[0][3]

    假设数组 a 中第 0 个元素的地址为 1000,那么每个一维数组的首地址如下图所示
    在这里插入图片描述
    为了更好的理解指针和二维数组的关系,我们先来定义一个指向 a 的指针变量 p:

    int (*p)[4] = a;
    

    括号中的*表明 p 是一个指针,它指向一个数组,数组的类型为int [4],这正是 a 所包含的每个一维数组的类型。

    [ ]的优先级高于*,( )是必须要加的,如果赤裸裸地写作int *p[4],那么应该理解为int *(p[4])p 就成了一个指针数组,而不是二维数组指针,这在《C语言指针数组》中已经讲到。
    对指针进行加法(减法)运算时,它前进(后退)的步长与它指向的数据类型有关,p 指向的数据类型是int [4],那么p+1就前进 4×4 = 16 个字节,p-1就后退 16 个字节,这正好是数组 a 所包含的每个一维数组的长度。也就是说,p+1会使得指针指向二维数组的下一行,p-1会使得指针指向数组的上一行。

    数组名 a 在表达式中也会被转换为和 p 等价的指针!

    下面我们就来探索一下如何使用指针 p 来访问二维数组中的每个元素。按照上面的定义:

    1. p指向数组 a 的开头,也即第 0 行;p+1前进一行,指向第 1 行。

    2. *(p+1)表示取地址上的数据,也就是整个第 1 行数据。注意是一行数据,是多个数据,不是第 1 行中的第 0 个元素,下面的运行结果有力地证明了这一点:

    #include <stdio.h>
    int main(){
        int a[3][4] = { {0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11} };
        int (*p)[4] = a;
        printf("%d\n", sizeof(*(p+1)));
        return 0;
    }
    

    运行结果:

    16
    
    1. *(p+1)+1表示第 1 行第 1 个元素的地址。如何理解呢?

    *(p+1)单独使用时表示的是第 1 行数据,放在表达式中会被转换为第 1 行数据的首地址,也就是第 1 行第 0 个元素的地址,因为使用整行数据没有实际的含义,编译器遇到这种情况都会转换为指向该行第 0 个元素的指针;就像一维数组的名字,在定义时或者和 sizeof& 一起使用时才表示整个数组,出现在表达式中就会被转换为指向数组第 0 个元素的指针。

    1. *(*(p+1)+1)表示第 1 行第 1 个元素的值。很明显,增加一个 * 表示取地址上的数据。

    根据上面的结论,可以很容易推出以下的等价关系:

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

    实例】使用指针遍历二维数组。

    #include <stdio.h>
    int main(){
        int a[3][4]={0,1,2,3,4,5,6,7,8,9,10,11};
        int(*p)[4];
        int i,j;
        p=a;
        for(i=0; i<3; i++){
            for(j=0; j<4; j++) printf("%2d  ",*(*(p+i)+j));
            printf("\n");
        }
        return 0;
    }
    

    运行结果:

    0   1   2   3
     4   5   6   7
     8   9  10  11
    

    指针数组和二维数组指针的区别

    针数组和二维数组指针在定义时非常相似,只是括号的位置不同:

    int *(p1[5]);  //指针数组,可以去掉括号直接写作 int *p1[5];
    int (*p2)[5];  //二维数组指针,不能去掉括号
    

    指针数组和二维数组指针有着本质上的区别:指针数组是一个数组,只是每个元素保存的都是指针,以上面的 p1 为例,在32位环境下它占用 4×5 = 20 个字节的内存。二维数组指针是一个指针,它指向一个二维数组,以上面的 p2 为例,它占用 4 个字节的内存。

    二维数组名做参数传递问题

    展开全文
  • 二维数组指针详解

    2018-01-20 15:00:54
    详细讲述了二维数组与指针之间的联系,对于学习C语言,理解指针数组吗,数组指针,数组与指针之间的关系有重要的帮助。仔细学习完该文档,详细你不会再为指针和数据而困惑。
  • 函数指针、函数名、二维数组指针做形参时的要注意的地方
  • 二维数组指针

    2020-01-24 20:19:20
    目录●´∀`●二维数组指针——行指针和列指针写在前面——“int[N]型”数据类型二维数组指针行指针列指针 二维数组指针——行指针和列指针 写在前面——“int[N]型”数据类型 “int[N]型”数据类型:C语言中并不...

    二维数组指针——行指针和列指针

    写在前面——“int[N]型”数据类型

    “int[N]型”数据类型:C语言中并不存在这个数据类型,为了便于理解二维数组,提出了此种数据类型。实际上可以理解为将二维数组(矩阵)划分为若干个行向量——int[N]型,N为矩阵列数。

    int a[3][4];//定义了一个三行四列的二维数组
    

    a代表二维数组a的首地址,第0行的地址,行地址。
    a+i代表第i行的地址,但并非增加i个字节,而是加上i行数组元素的字节数(每行数组元素占字节数相同)。
    视二维数组a[3][4]为一维数组,只不过每个元素为一个数组,具有3个元素,分别为a[0],a[1],a[2],每个a[i]中又有四个元素。
    把二维数组a看成一维数组,有3个“int[4]型”元素,因此根据一维数组解引用有:
    解引用:*(a+i)等价于a[i]
    取地址:&a[i]等价于(a+i)

    二维数组特殊性在于:*(a+i)和a[i] 是一个数组名,也是一个地址。在例子中,每一个a[i]有4个元素。
    访问a[i][j](后面会解释原因):
    a[i][j]等价于(*(a+i))[j]等价于*(*(a+i)+j)等价于*(a[i]+j)

    二维数组指针

    可以使用 行指针 或者 列指针 对二维数组元素进行访问。
    形参声明为二维数组的行指针时,列数必为常量。
    形参声明为二维数组的列指针时,列数可为变量。

    行指针

    int (*p)[4];//定义了一个行指针
    p = a;
    int *pp[4];//定义了一个指针数组,数组中每一个元素都是一个整型指针
    

    第一行语句定义了一个行指针(基类型是"int[4]"型(带双引号哈)),第2行语句对指针进行初始化,让其指向第0行的“int[4]型”元素,第3行语句定义了一个指针数组,数组中每一个元素都是一个整型指针,注意区分。

    *(a+i)或*(p+i)解引用将a+i或p+i这个第i行的行地址转化为了第i行第0列的地址。
    *(a+i)+j或*(p+i)+j将指针从第0列移动到第j列,指向第i行第j列的元素,再进行一次解引用*(*(a+i)+j)或*(*(p+i)+j)就能取出第i行第j列的值,即a[i][j]

    列指针

    按列指针访问二维数组元素:根据相对偏移量

    int *p;
    p=&a[0][0];
    

    初始化也可以写成p=a[0] ,指向第0行第0列,访问元素方法:*(p+i*n+j)或者p[i*n+j]

    附注:1.注意区分行指针和列指针定义和初始化的不同之处,以及使用行指针和列指针取二维数组值的不同方式。
    2.本文建议复习食用,可能有错误对初学者产生误导。
    3.本文内容大部分为MOOC-哈工大-C语言程序设计精髓中课件与《C语言程序设计》(第三版)书中内容的复制和整理。
    4. 建议配合《指针-一维数组和指针关系-字符指针》中的一维数组和指针关系复习。
    5.如有错误(肯定有好多),欢迎指正。

    展开全文
  • 文章目录一维数组指针和二维数组指针的定义一维数组指针和二维数组指针用于索引数组元素一维数组指针和二维数组指针的可视化解读 一维数组指针和二维数组指针的定义 一维数组指针的定义就是普通指针的定义 指针变量...

    一维数组指针和二维数组指针的定义

    • 一维数组指针的定义就是普通指针的定义 指针变量类型 *指针变量名称 --> int *p
    • 二维数组指针变量的定义略微复杂:指针变量类型 *指针变量名称[二维数组的列数] --> int(*p2)[3]

    一维数组指针和二维数组指针用于索引数组元素

    在这里插入图片描述

    一维数组指针和二维数组指针的可视化解读

    在这里插入图片描述

    使用二维数组指针的实例演示

    • 题目:使用二维数组指针,通过输入行数和列数,打印出二维数组对应的索引的值。
      在这里插入图片描述【代码】
    #define _CRT_SECURE_NO_WARNINGS
    #include<stdio.h>
    void main() {
    	int a, b;
    	printf("c数组是一个2行3列的数组\n");
    	printf("请输入您想要索引的行和列\n");
    	scanf("%d %d",&a,&b);
    
    	int c[][3] = { {1,2,3},
    				   {4,5,6} };
    	int(*p)[3] = c;
    
    	printf("c[%d][%d]=%d\n", a, b, *(*(p + a) + b));  //使用指针的索引方式
    
    	printf("c[%d][%d]=%d\n", a, b, c[a][b]);	// 使用数组直接索引
    }
    
    展开全文
  • 可以看到,实质上二维数组在物理上是连续存储的,但是分析二维数组指针的时候更应该分析二维数组的逻辑结构,如下所示: 应当看到,二维数组的在逻辑上是多个行数个一维数组的集合,这种理解方式至关重要。 在这种...

    先看一个例子:

    int a[3][4];
    int (*p)[4]=a;
    *(p[0]+2)=2;//这句话是什么意思
    

    首先,我们必须明白二维数组的逻辑结构和物理结构
    这是物理结构
    可以看到,实质上二维数组在物理上是连续存储的,但是分析二维数组指针的时候更应该分析二维数组的逻辑结构,如下所示:
    二维数组逻辑结构
    应当看到,二维数组的在逻辑上是多个行数个一维数组的集合,这种理解方式至关重要。

    在这种观点之下,我们来看一个问题。即a[0]的含义是什么?既然二维数组可以看做行数个一维数组的集合,那么a[0]是不是可以看做是一维数组的数组名?回忆我们用下标来指示数组的方式:a[0][1],是不是就是在a[0]当成数组名?那么我们就又要注意到,如果a[0]的含义是数组名,那么是否也像一维数组那样,可以当做该一维数组的首地址?答案是肯定的。即此刻我们可以认为,在二维数组中,a[i]存放着该行数组的首地址,那么,* (a[0]+2)的含义就很明显了。
    我们可以对 *(a[0]+2)这个式子采用这样的理解方式:我们设定第0行的行数组为数组b,那么此刻a[0]的含义就是b的数组名b,那么原式子可以理解为 *(b+2)。即b这一数组的第三个元素(下标从0开始)即 * (a[0]+2)= * (b+2)=b[2]=a[0][2].
    理解了a[i]是第i行数组的首地址的问题之后,我们再回到开头的那个问题。

    int (*p)[4]=a;
    *(p[0]+2)=2;//这句话是什么意思
    

    首先明确,int (*p)[4]=a;中的p是二维数组指针。与之对应的是指针数组int *p[4]。
    如何区分和记忆?我们记得,[]的优先级是很高的,于是int * p[4]中的p和[4]是密不可分的,这就意味着这里的p是一组数组的名字,而数组的类型是指针;与之对应的是int * §[4],这里p是二维数组的指针。
    二维数组的指针是什么?直观来看,和一维数组类似,用以指向整个二维数组。
    在这里插入图片描述
    就是这个图里的a。但是由于其是一个数组指针,所以要注意,它每次加1的步进值是4个数组单元。这就要回到逻辑上的二维数组结构了。
    在这里插入图片描述

    一般,我们会将二维数组的名字赋给数组指针p。p所指向的正是之前我们提到过的a[0]。而p+i指向的正是a[i]。那么**上面我们说过了,a[i]实质上是对应行的数组名字,也即该数组的地址,也是该行数组的指针。**那么可以看到,**这里p+i是指向第i行数组地址的指针,也就是第i行数组地址的地址。**既然是地址的地址,那么显而易见,需要两次解引用才可以取到数组中的某个元素。
    最常见的用法像是这样:
    *( *(p+i)+j)。我们来分析这个操作。首先是 *(p+i),这里 (p+i)==a[i]。但是注意了,反复强调过a[i]是i行数组的数组名,所以也可以理解为 (p+i)==a[i]=b;其中b是我们假定的第i行的数组名。那么将b代入这个式子可以看到原来的式子为:
    (b+j)。这个式子是不是就很好理解?就是b这个数组的第j号元素嘛。而b这个数组是a的第i行数组,于是很容易知道,绕了半天,( (p+i)+j)=a[i][j]。
    但是我们离开头的问题似乎还是差一点。这个
    (p[0]+2)=2;中的p[0]是什么呢?这里其实可以从两个方面理解,一个,可以将p和a一起来看,那么p[0]==a[0],那么a[0]+2指的就是第0行第2号元素的地址,外面加个解引用的符号即是取第0行的第2号元素。另外一个理解是p[0]等价于 *(p+0),再结合刚才的分析,那么就可以理解了。

    上面说了基本的原理,下面提炼下分辨的要点:

    1. int *p[4]是二维数组指针,表示的实际是二维数组的首地址,也是该二维数组中的一维数组的地址的地址。
    2. int (*p)[4]是指针数组。实质是元素为指针的一维数组。
    3. 分析二维数组时,如果出现了二维数组指针,那么取某个元素的时候要两次解引用,或者利用p[0]这样的形式做一个默认的转换。
    展开全文
  • 二维数组指针问题

    2019-08-15 09:27:33
    编写一个程序,初始化一个double类型的3×5二维数组,使用一个处理变长数组的函数将其拷贝至另一个二维数组中。还要编写一个以变长数组为形参的函数以显示两个数组的内容。这两个函数应该能处理任意N×M数组。(《C ...
  • C语言中,指针是一个复杂但又灵活多变的知识点,我们知道,在一维数组中,对于一个数组a[],*a,a,&a,都表示a的首地址,但如果与二维数组混合使用,就显得更为复杂了。例如对于一个二维数组 a[2][4]={{1,2.3},{4...
  • 主要介绍了C++指针数组、数组指针、数组名及二维数组技巧汇总,对于深入理解C++数组与指针来说非常重要,需要的朋友可以参考下
  • c/c++ 二维数组指针参数传递 矩阵计算实例

    千次阅读 多人点赞 2019-03-30 00:57:19
    今天我将试图用沙雕文风解释二维数组的知识;D 1问题 首先我们来看一下问题 FBIwarning:建议在阅读答案前,独立思考,先自行尝试,遇到问题再继续阅读。 怎么样!看起来就很难对吧!实际上!它确实不...
  • c++二维数组指针详解

    2020-04-13 10:42:13
    int main() { int a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};... //上面可以这么理解:对于一维数组a[],数组名a是第一个元素a[0]的地址,那么对于二维数组a[][],一维数组名a[0]是它的第一个元素a[0][...
  • c语言中经常需要通过函数传递二维数组,有三种方法可以实现,如下: 方法一, 形参给出第二维的长度。 例如: #include void func(int n, char str[ ][5] ) { int i; for(i = 0; i < n; i++) printf("/nstr...
  • //总结关于二维数组指针和函数形参实参 //1.指针: **p 和(*p)[2]都可以指向二维数组 **p是二维指针,系统不知道+1是加多少,(*p)[2]则明确指出每+1是指2(int) //2.实参: function(p , arr) ‘p’指**p (*p)[2]...
  • 二维数组数组指针详解

    多人点赞 2020-07-26 18:18:53
    二维数组 深入理解二维数组 首先定义一个二维数组 int a[2][3]={{1,2,3},{4,5,6}}; #or int a[2][2]={1,2,3,4}; 新的理解:我们可以这样认为,a可以看作是一个一维数组,包含2个元素,每个元素恰好是包含3个整型...
  • 二维数组指针传递

    千次阅读 2018-03-25 19:02:37
    向C函数中传递指向二维数组指针参数 先来回顾一下一维数组,一维数组的数组名即为指向该数组的指针,该指针值保存了数组存放在内存中的一块连续区域的起始地址;数组的下标表示了这片内存区域的某存储区相对于...
  • 关于用指针方式访问二维数组的问题 首先说明几种类型: int a[2][4] = { 1,2,3,4,5,6,7,8 };//二维数组 int **p; //二重指针跨度为sizeof(int *) int(*q)[4]; //该语句是定义一个指向数组的指针,指向含4个...
  • 今天使用某个函数,其中的参数是类型为char**, 使用了一个固定的二维数组,将其赋值给予,编译时产生警告;在运行的调用的函数(其中没有任何对字符串内容的修改)...后来是声明了一个指针数组,将用二维数组标识的...
  • 二维数组指针的理解

    千次阅读 多人点赞 2018-07-16 16:51:00
    假如有二维数组arr[][]. arr表示数组第一行第一个元素的地址,也可用来表示第一行的总体地址。同理的也有arr[0]。 arr+1表示二维数组第二行第一个元素的地址,也可以用来表示第二行的总体地址。同理的也有arr[1]。...
  • 二维数组的定义: int **matrix ; -----------见图的操作那篇文章里面的定义 或者这篇文章提供了另外一种方法。 http://c.biancheng.net/view/2022.html 二维数组在概念上是二维的,有行和列,但在内存中...
  • 对于二维数组 二级指针以及数组指针的讨论。对于二维数组 二级指针以及数组指针的讨论
  • c++二维数组指针

    万次阅读 多人点赞 2017-12-26 21:47:04
    1.定义指针指向二维数组 为了方便根据用户输入动态定义二维数组的行和列,引入变量rowsNum(行),colsNum(列)。 以定义5行4列的二维数组为例, int rowsNum = 4; int colsNum = 5; float** a = new float*...
  • 主要介绍了C语言二维数组指针指向问题,文中不建议用二级指针来访问二维数组,需要的朋友可以参考下
  • c++return返回二维数组

    2019-01-06 19:41:20
    在c++中,经常调用函数,而子函数经常要返回的值是数组,无论一维数组还是二维数组都需要运用到指针的知识。一维数组不再过多叙述,给了一个实例如何返回二维数组,希望对大家有帮助(主要用到指针的知识,看不懂的...
  • 9#include using namespace std; int main() { void fun(int *p1,int *p2,int w,...这个程序中,p1[i*w+j]代表啥啊,是二维数组的表达方式? 那当i=1时,表示P1[2+0],这不就是P1【2】【0】吗,那P1【1】【0】咋表示啊
  • // 这里直接当作是数组赋值。  }  }    // 下面是释放空间     for  ( int  i=0; i; i++)  {    delete [] result[i];  }  delete [] result; int main()...
  • a存了3个一维数组,是一维数组的名称,首指向第一行一位数组的首地址 a[i]是第i行一位数组的名称,首指向一位数组的第一个数。 我把*理解成读地址进去。 *a+1 根据运算符顺序,先运算a,a指向首个元素1000,读出地址...
  • *(*(p+i)+C)=a[i][C]
  • 主要介绍了C++中用new创建二维数组指针数组实例代码,非常不错,具有参考借鉴价值,需要的朋友参考下

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 107,093
精华内容 42,837
关键字:

二维数组指针