C/C++二维数组指针(指向二维数组的指针)详解

多维数组与指针

用指针变量可以指向一维数组中的元素,也可以指向多维数组中的元素。

1) 多维数组元素的地址
设有一个二维数组 a,它有 3 行 4 列。它的定义为:
    int a[3][4]={ {1,3,5,7},{9,11,13,15},{17,18,21,23}};
a 是一个数组名。a 数组包含 3 行,即 3 个元素:a [0],a [1],a [2]。而每一元素又是一个一维数组,它包含 4 个元素 (即 4 个列元素),例如,a [0] 所代表的一维数组又包含 4 个元素: a [0][0], a [0][1], a [0][2], a [0][3],如图所示。可以认为二维数组是 “数组的数组”,即数组 a 是由 3 个一维数组所组成的。
 

《C/C++二维数组指针(指向二维数组的指针)详解》

从二维数组的角度来看,a 代表二维数组首元素的地址,现在的首元素不是一个整型变量,而是由 4 个整型元素所组成的一维数组,因此 a 代表的是首行的起始地址 (即第 0 行的起始地址,&a [0]),a+1 代表 a [1] 行的首地址,即 & a [1]。

a [0],a [1],a [2] 既然是一维数组名,而 C++ 又规定了数组名代表数组首元素地址,因此 a [0] 代表一维数组 a [0] 中 0 列元素的地址,即 & a [0][0]。a [1] 的值是 & a [1][0],a [2] 的值是 & a [2][0]。
 

《C/C++二维数组指针(指向二维数组的指针)详解》

0 行 1 列元素的地址可以直接写为 & a [0][1],也可以用指针法表示。a [0] 为一维数组名,该一维数组中序号为 1 的元素显然可以用 a [0]+1 来表示。

欲得到 a [0][1] 的值,用地址法怎么表示呢?既然 a [0]+1 是 a [0][1] 元素的地址,那么,*(a [0]+1) 就是 a [0][1] 元素的值。而 a [0] 又是和 *(a+0) 无条件等价的,因此也可以用 *(*(a+0)+1) 表示 a [0][1] 元素的值。依此类推,*(a [i]+j) 或 *(*(a+i)+j) 是 a [i][j] 的值。
 

《C/C++二维数组指针(指向二维数组的指针)详解》

2) 指向多维数组元素的指针变量
① 指向数组元素的指针变量
【例1】输出二维数组各元素的值。这里采用的方法是用基类型为整型的指针变量先后指向各元素,逐个输出它们的值。(三种方法均可)

#include <iostream>
using namespace std;
int main()
{
	int a[3][4] = { 1,3,5,7,9,11,13,15,17,19,21,23 };
	//p是基类型为整型的指针变量
	//p = a[0]  等同于 p = &a[0][0];  也即0行首元素的地址
	int* p;                              
	for (p = a[0]; p < a[0] + 12; p++)
		cout << *p << " ";

	for (int i = 0;i<3;i++)
	{
		for (int j = 0;j<4;j++)
		{
			//cout << *(*(a + i) + j) << " ";
			cout << *(a[i] + j) << " ";
		}
	}
	cout << endl;
	return 0;
}

关于指向数组元素的指针变量的几点说明:

  • p 是指向整型数据的指针变量,在 for 语句中对 p 赋初值 a [0],也可以写成 “p=&a [0][0]”。
  • 循环结束的条件是 “p<a [0]+12”,只要满足 p<a [0]+12,就继续执行循环体。
  • 执行 “cout<<*p;” 输出 p 当前所指的列元素的值,然后执行 p++,使 p 指向下一个列元素。

②指向由 m 个元素组成的一维数组的指针变量

可以定义一个指针变量,它不是指向一个整型元素,而是指向一个包含 m 个元素的一维数组。这时,如果指针变量 p 先指向 a [0](即 p=&a [0]),则 p+1 不是指向 a [0][1],而是指向 a [1],p 的增值以一维数组的长度为单位。

《C/C++二维数组指针(指向二维数组的指针)详解》

【例2】输出二维数组任一行任一列元素的值。

#include <iostream>
using namespace std;
int main( )
{
    int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};
    int (*p)[4],i,j;
    cin>>i>>j;
    p=a;
    cout<<*(*(p+i)+j)<<endl;
    return 0;
}

由于执行了 “p=a”,等同于”p = &a[0] “使 p 指向 a [0]。因此 p+2 是二维数组 a 中序号为 2 的行的起始地址 (由于 p 是指向一维数组的指针变量,因此 p 加 1,就指向下一个一维数组)。*(p+2)+3 是 a 数组 2 行 3 列元素地址。*(*(p+2)+3) 是 a [2][3] 的值。

《C/C++二维数组指针(指向二维数组的指针)详解》

3) 用指向数组的指针作函数参数
一维数组名可以作为函数参数传递,多维数组名也可作函数参数传递。

【例3】输出二维数组各元素的值。题目与例1相同,但本题用一个函数实现输出,用多维数组名作函数参数。

#include <iostream>
using namespace std;
int main( )
{
    void output(int (*p)[4]);  //函数声明 
    int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};
    output(a);  //多维数组名作函数参数
    return 0;
}

//相当于  p = a;或者 p = &a[0];
void output(int (*p)[4])  //形参是指向一维数组的指针变量
{
    int i,j;
    for(i=0;i<3;i++)
        for(j=0;j<4;j++)
            cout<<*(*(p+i)+j)<<" ";
    cout<<endl;
}

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

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

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

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

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

二级指针

使用二级指针初始化一级指针

《C/C++二维数组指针(指向二维数组的指针)详解》

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
enum
{
    Success,NameErr,SexErr,StrNumErr,ScoreErr
};
typedef struct stu
{
    char *name;
    char *sex;
    char *strNum;
    float *score;
}STU;
int init(STU ** p)
{
    *p = (STU *)malloc(sizeof(STU));//*p就是ps,申请一块空间里面存放4个不同类型的指针,将首地址赋值给ps
    //初始化一级指针,使这4个不同类型的指针都有所指向
    (*p)->name = (char *)malloc(sizeof(100));
    if((*p)->name == NULL)
        return NameErr;
    (*p)->sex = (char *)malloc(sizeof(char));
    if((*p)->sex == NULL)
        return SexErr;
    (*p)->strNum = (char *)malloc(sizeof(30));
    if((*p)->strNum == NULL)
        return StrNumErr;
    (*p)->score = (float *)malloc(sizeof(float));
    if((*p)->score == NULL)
        return ScoreErr;
    return Success;
}
int main(void)
{
    STU * ps = NULL;

    int ret = init(&ps);
    if(ret != Success)
        return -1;
    strcpy(ps->name,"wahaha");
    *(ps->sex) = 'x';
    strcpy(ps->strNum,"语文");
    *(ps->score) = 66.5;

    printf("姓名:%s\n性别:%c\n科目:%s\n分数:%.2f\n",ps->name,*(ps->sex),ps->strNum,*(ps->score));
    return 0;
}
    原文作者:coder_Alger
    原文地址: https://blog.csdn.net/weixin_42289227/article/details/123750707
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞