C语言之三维数组

C语言之三维数组前言 之前学习 C 语言的时候仅仅是掌握了二维数组 但是并没有对三维数组进行研究 今天的代码提前搞完了 摸摸鱼 对去年研究的三维数组的相关知识发布一下 期待能够帮助到有缘人 实际上 当你阅读此篇文章时 我假设你已经对 C 语言的二维数组非常熟悉了 并且非常熟悉数组与指针之间的关系 如果没有达到此要求 那直接翻篇 不要看 等待基础掌握扎实后再来学习此篇文章 一 看图说话 一眼看三维数组二 首先看下三维数组的遍历 include stdio h voidmain 三维数组

前言:


之前学习C语言的时候仅仅是掌握了二维数组,但是并没有对三维数组进行研究,此情此景. . .那就让我对去年研究的三维数组的相关知识发布一下,也许能够帮到你!实际上,当你阅读此篇文章时,我假设你已经对C语言的二维数组非常熟悉了,并且非常熟悉数组与指针之间的关系,如果没有达到此要求,那直接翻篇,不要看,我估摸着你看不大懂。当然了,也可以尝试看看!


一、先看看三维数组长啥样吧

在这里插入图片描述
这个图是我网上拷贝的,搞这张图片的大哥,,希望你手下留情,不要打我哦,我胆子小。

二、首先看下三维数组的遍历

#include "stdio.h" void main(){ 
      //三维数组 int a[2][3][4] = { 
      { 
      { 
     6,2,3,4}, { 
     5,11,15,8}, { 
     8,20,10,11} }, { 
      { 
     0,0,3,4}, { 
     5,0,7,8}, { 
     8,1,18,31} } }; int i, j, k; int(*p)[3][4]; //p是指向二维数组的指针  p = a; //p指向三维数组的0行 (也即p指向一个二维数组)  //p=&a[0]; //与上等价 printf(" 【三维数组的遍历】:\n\n"); for (i = 0; i < 2; i++) { 
      for (j = 0; j < 3; j++) { 
      for (k = 0; k < 4; k++) { 
      //元素值遍历 :  printf("a[%d][%d][%d]=%-9d ", i, j, k, *(*(*(p + i) + j) + k));//元素值  printf("a[%d][%d][%d]=%-9d ", i, j, k, *(*(a[i] + j) + k)); //元素值  printf("a[%d][%d][%d]=%-9d ", i, j, k, *(a[i][j] + k)); //元素值  printf("a[%d][%d][%d]=%-9d ", i, j, k, *(&a[i][j][k])); //元素值  printf("a[%d][%d][%d]=%-9d ", i, j, k, a[i][j][k]); //元素值  printf("a[%d][%d][%d]=%-9d\n", i, j, k, p[i][j][k]); //元素值  //元素地址遍历:  // printf("&a[%d][%d][%d]=%-9d ", i, j, k, *(*(p + i) + j) + k); //元素地址  // printf("&a[%d][%d][%d]=%-9d ", i, j, k, *(a[i] + j) + k); //元素地址 // printf("&a[%d][%d][%d]=%-9d ", i, j, k, a[i][j] + k); //元素地址 // printf("&a[%d][%d][%d]=%-9d\n", i, j, k, &a[i][j][k]); //元素地址 //由于少了整体括号,所以出现错误的遍历,只有a[0][0][0],a[0][1][0],a[0][2][0],a[1][0][0],a[1][1][0],a[1][2][0]正确 // // printf("a[%d][%d][%d]=%-9d ", i, j, k, (*(p + i) + j) + k); //错误,由于最外层少括号  // printf("a[%d][%d][%d]=%-9d ", i, j, k, (a[i] + j) + k); //错误,由于最外层少括号  // printf("a[%d][%d][%d]=%-9d ", i, j, k, *a[i][j] + k); //错误,由于最外层少括号  // printf("a[%d][%d][%d]=%-9d\n", i, j, k, *&a[i][j][k]); //正确  } printf("\n"); } } } 【【【注意】】】:在对地址取*运算时, 一定要加“()”,也即对地址整体取“括号”,然后*,否则将得不到期望值! 比如:*(a[i] + j) + k表示 & a[i][j][k] ====> 也即元素a[i][j][k]的地址。 对其取*运算应该是*(*(a[i] + j) + k) ====> 表示是元素a[i][j][k]的值。 而不能写成这样:**(a[i] + j) + k ====> 并不是我们期望的各元素值! 当然了:对于&a[i][j][k]求其元素值时,可以对其直接取*,不必在意()整体的问题! 【分析如下】: for (i = 0; i < 2; i++) { 
      for (j = 0; j < 3; j++) { 
      for (k = 0; k < 4; k++) { 
      printf("a[%d][%d][%d]=%-9d ", i, j, k, **(a[i] + j) + k); //(*(p + i) + j) + k, *a[i][j] + k同理 } } } 【输出结果】:[6],7,8,9 [5],6,7,8 [8],9,10,11 [0],1,2,3 [5],6,7,8 [8],9,10,11 【很明显】:只有a[0][0][0], a[0][1][0], a[0][2][0], a[1][0][0], a[1][1][0], a[1][2][0]正确,其他值并不是个元素的值! 【假如】: i=0, j=0, k=0; ==> **(a[i]+j)+k ===> **(a[0]+0)+0 ===> *(*(a[0]+0))+0 ===> *(a[0][0])+0 ===>*(a[0][0])+0 ===> *(&a[0][0][0])+0= 6 i=0, j=0, k=1; ==> **(a[i]+j)+k ===> **(a[0]+0)+1 ===> *(*(a[0]+0))+1 ===> *(a[0][0])+1 ===>*(a[0][0])+1 ===> *(&a[0][0][0])+1= 7 i=0, j=0, k=2; ==> **(a[i]+j)+k ===> **(a[0]+0)+2 ===> *(*(a[0]+0))+2 ===> *(a[0][0])+2 ===>*(a[0][0])+2 ===> *(&a[0][0][0])+2= 8 i=0, j=0, k=3; ==> **(a[i]+j)+k ===> **(a[0]+0)+3 ===> *(*(a[0]+0))+3 ===> *(a[0][0])+3 ===>*(a[0][0])+3 ===> *(&a[0][0][0])+3= 9 其他情况亦是如此! 

三、看下三维数组中的地址系列

#include "stdio.h" void main() { 
      int a[2][3][4] = { 
      { 
      { 
     6,2,3,4}, { 
     5,11,15,8}, { 
     8,20,10,11} }, { 
      { 
     0,0,3,4}, { 
     5,0,7,8}, { 
     8,1,18,31} } }; //相当于有2个二维数组a[0] [3][4]和a[1] [3][4]------其中a[0]和a[1]为二维数组名!  //【【【第1个二维数组】】】: 【a[0]相当于二维数组的名字】 printf("【第1个二维数组】:\n"); printf("0行首地址: %d\n", &a[0][0]); //0行首地址 (a[0][0]相当于一维数组的名字) 【int (*)[4]型】 printf("1行首地址: %d\n", &a[0][1]); //1行首地址 (a[0][0]相当于一维数组的名字) 【int (*)[4]型】 printf("2行首地址: %d\n\n", &a[0][2]); //2行首地址 (a[0][0]相当于一维数组的名字) 【int (*)[4]型】 printf("0行首地址: %d\n", a[0]); //0行首地址 (a[0][0]相当于一维数组的名字) 【int (*)[4]型】 printf("1行首地址: %d\n", a[0] + 1); //1行首地址 (a[0][0]相当于一维数组的名字) 【int (*)[4]型】 printf("2行首地址: %d\n\n", a[0] + 2); //2行首地址 (a[0][0]相当于一维数组的名字) 【int (*)[4]型】 printf("0行0列首地址: %d\n", a[0][0]); //0行0列元素地址 (a[0][0]相当于一维数组的名字)  printf("1行0列首地址: %d\n", a[0][1]); //1行0列元素地址 (a[0][0]相当于一维数组的名字) printf("2行0列首地址: %d\n\n", a[0][2]); //2行0列元素地址 (a[0][0]相当于一维数组的名字)  printf("0行0列元素地址: %d\n", &a[0][0][0]);//0行0列元素地 (a[0][0]相当于一维数组的名字)  printf("1行0列元素地址: %d\n", &a[0][1][0]);//1行0列元素地 (a[0][0]相当于一维数组的名字)  printf("2行0列元素地址: %d\n\n", &a[0][2][0]);//2行0列元素地址(a[0][0]相当于一维数组的名字)  printf("0行0列元素值: %d\n", a[0][0][0]);//0行0列元素值 (a[0][0]相当于一维数组的名字)  printf("1行0列元素值: %d\n", a[0][1][0]);//1行0列元素值 (a[0][0]相当于一维数组的名字)  printf("2行0列元素值: %d\n\n", a[0][2][0]);//2行0列元素 (a[0][0]相当于一维数组的名字)  printf("0行0列元素值: %d\n", *(*(a[0] + 0) + 0));//a[0][0][0] (a[0]相当于二维数组的名字)  printf("1行0列元素值: %d\n", *(*(a[0] + 1) + 0));//a[0][1][0] (a[0]相当于二维数组的名字)  printf("2行0列元素值: %d\n\n", *(*(a[0] + 2) + 0));//a[0][2][0] (a[0]相当于二维数组的名字)  //【【【第2个二维数组】】】: 【a[1]相当于二维数组的名字】 printf("\n【第2个二维数组】:\n"); printf("0行首地址: %d\n", &a[1][0]); //0行首地址 【int (*)[4]型】 printf("1行首地址: %d\n", &a[1][1]); //1行首地址 【int (*)[4]型】 printf("2行首地址: %d\n\n", &a[1][2]); //2行首地址 【int (*)[4]型】 printf("0行首地址: %d\n", a[1]); //0行首地址 【int (*)[4]型】 printf("1行首地址: %d\n", a[1] + 1); //1行首地址 【int (*)[4]型】 printf("2行首地址: %d\n\n", a[1] + 2); //2行首地址 【int (*)[4]型】 printf("0行0列元素地址: %d\n", &a[1][0][0]);//0行0列元素地址 printf("1行0列元素地址: %d\n", &a[1][1][0]);//1行0列元素地址 printf("2行0列元素地址: %d\n\n", &a[1][2][0]);//2行0列元素地址 printf("0行0列元素值: %d\n", a[1][0][0]);//0行0列元素值  printf("1行0列元素值: %d\n", a[1][1][0]);//1行0列元素值  printf("2行0列元素值: %d\n\n", a[1][2][0]);//2行0列元素值  printf("0行0列元素值: %d\n", *(*(a[1] + 0) + 0));//0行0列元素值  printf("1行0列元素值: %d\n", *(*(a[1] + 1) + 0));//1行0列元素值  printf("2行0列元素值: %d\n", *(*(a[1] + 2) + 0));//2行0列元素值  printf("2行2列元素值: %d\n", *(*(a[1] + 2) + 2));//2行2列元素值  //【【【其他问题】】】: printf("\n\n【其他问题】:"); printf("\na[0]= %d\n", a[0]); //指向一维数组的指针 int (*)[4]型(a[0]是二维数组名) printf("a[1]= %d\n\n", a[1]); //指向一维数组的指针 int (*)[4]型(a[1]是二维数组名) printf("&a[0]= %d\n", &a[0]); //指向二维数组的指针 int (*)[3][4]型(a[0]是二维数组名) printf("&a[1]= %d\n", &a[1]); //指向二维数组的指针 int (*)[3][4]型(a[1]是二维数组名) printf("&a[0]+1= %d\n\n", &a[0] + 1);//指向二维数组的指针 int (*)[3][4]型 printf("a= %d\n", a); //指向二维数组的指针 int (*)[3][4]型(a是三维数组名) printf("a+1= %d\n", a + 1); //指向二维数组的指针 int (*)[3][4]型 printf("\n"); } 

四、详解三维数组


//首先我们回顾一下二维数组: 二维数组是“数组的数组”,也即二维数组是由一维数组构成的! 【例如】:int a[3][4]; 二维数组是数组的数组,也即二维数组a是3个一维数组组成的! 相当于定义了3个一维数组:int a[0][4], a[1][4], a[2][4]; 此处是把a[0], a[1], a[2]看作是一维数组的名字。 则二维数组就转换成一维数组了,就可以在一维数组的领域内解决问题了! 且在二维数组中存在以下等式关系: a[i]+j === *(a+i)+j === &a[i][j] //这是各元素地址 * (a[i]+j) === *(*(a +i)+j) === *(&a[i][j]) //这是各元素值 且在指向一维数组的指针中存在以下关系:(int(*p)[4]) int(*p)[4];//指向一维数组的指针 若p = a; //使得p指向二维数组0行首地址 则有以下等式必然成立: *(p+i)+j === *(a+i)+j === a[i]+j === &a[i][j] //这是各元素地址 **(p+i)+j) === **(a+i)+j) === *(a[i]+j) === * &a[i][j] ===p[i][j] //这是各元素值 //再来看三维数组: 通过对二维数组的理解,我们可以知道,三维数组是“数组的数组的数组” 也即三维数组是由二维数组构成的,而二维数组又是由一维数组构成的! 例如 int a[2][3][4]; 可以把三维数组看成是2个二维数组构成的,而二维数组又是由一维数组构成的! 也即本题定义了2个二维数组int a[0][3][4]和a[1][3][4](此处是把a[0], a[1]看作是二维数组的名字)! 而二维数组又是由一维数组构成的,所以此处的二维数组又是由3个一维数组构成的。 也即一维数组a[0][0][4], a[0][1][4], a[0][2][4], a[1][0][4]......!(此处把a[0][0], a[0][1], a[0][2]......看作是一维数组的名字) 也即 int a[0][0][4] //此处是把a[0][0]看做是一维数组的名字,它包含4个元素 int a[0][1][4] //此处是把a[0][1]看做是一维数组的名字,它包含4个元素 int a[0][2][4] //此处是把a[0][2]看做是一维数组的名字,它包含4个元素 int a[1][0][4] //此处是把a[1][0]看做是一维数组的名字,它包含4个元素 int a[1][1][4] //此处是把a[1][1]看做是一维数组的名字,它包含4个元素 int a[1][2][4] //此处是把a[1][2]看做是一维数组的名字,它包含4个元素 有了上述的理解之后,我们就可以对三维数组进一步认识了! 在二维数组中存在以下等式关系: a[i] + j === *(a + i) + j === &a[i][j](等式一) //这是各元素地址 上述说了:三维数组是由二维数组构成的,也即上述三维数组是由2个二维数组a[0]和a[1]构成。 对(等式一)进行替换: 在(等式一)中: a[i] + j === > a为二维数组的名字, i和j分别为二维数组的行和列; 所以在三维数组中:a[i][j] + k === > a[i]为二维数组的名字,j和k为相应的二维数组的行和列。 那么由此在三维数组中的等式也出现了: a[i] + j === *( a + i) + j === & a [i][j](a为二维数组的名字, i和j分别为二维数组的行和列) a[i][j] + k === *(a[i] + j) + k === & a[i][j][k](a[i]为二维数组的名字, j和k分别为二维数组的行和列) ********************************************************************************************* 【【【指向二维数组的指针】】】: 同样,在二维数组中,存在指向一维数组的指针int(*p)[]; 那么在三维数组中,同样存在指向二维数组的指针int(*p)[][]; 【【【在二维数组中】】】: int(*p)[4];//指向一维数组的指针 若p = a; //使得p指向二维数组0行(实际上也就是p指向一维数组) 则有以下等式必然成立: *(p + i) + j == = *(a + i) + j == = a[i] + j == = &a[i][j] //各元素地址(a表示二维数组的名字,i,j是相应的行和列) * (*(p + i) + j) == = *(*(a + i) + j) == = *(a[i] + j) == = *(&a[i][j])//这是各元素值 【【【同样在三维数组中】】】: int(*p)[3][4]; //指向二维数组的指针 如若p = a; //p指向三维数组的0行(实际上也就是p指向二维数组) 则同样有以下等式成立: *(*(p + i) + j) + k) == = *(a[i] + j) + k == = a[i][j] + k == = &a[i][j][k] //这是各元素地址(a[i]表示二维数组的名字,j,k是相应的行和列) * (*(*(p + i) + j) + k)) == = *(*(a[i] + j) + k) == = *(a[i][j] + k) == = *&a[i][j][k] == = a[i][j][k] //这是各元素地址 同样在对地址取“*”运算符(求元素值)时,要对地址整体取“()”,然后“*”,这和二维数组中的道理是一样的! 在三维数组中,始终要知道a[i]代表二维数组名!这样就可以在二维数组的基础之上照猫画虎了! 

温馨提示:由于时间关系,运行结果我就不贴图了,程序是完全正确的,大家拿去自己运行,这都是我自己去年学习C语言的时候做的笔记,均为原创,直到今天才发出来,希望能够帮助到你!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/199447.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月20日 下午12:57
下一篇 2026年3月20日 下午12:58


相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号