基础C++教学⮱⮱011【C中多维数组指针探究】2019-12-24

←↑→↓↖↙↗↘↕⏤
unicode=Geometric Shapes
▶ 仅仅个别字不同的时候的对比标识

◉ 着重强调

  ◆ 1、
  ◆ 2、
  ◆ 3、

  
  
  
  
  
  
  
  

Miscellaneous Symbols


Dingbats
✍ 重点记忆,个人总结的点,或者知识。
✎✎

  •  多维数组指针探究

  假设有如下多维数组定义(数组名重名,不能在同一个程序中运行):

int b[3][4]={0,1,2,3,4,5,6,7,8,9,10,11};
int b[3][4][2]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23};
int b[2][3][3][3]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53};

  其中4维数组具体图形结构如下(2维、3维同理可推):

  下面来看各不同维度的数据,在数组名(数组首地址)直接进行加1操作的时候,指针跨内存区域的步长情况:

  根据上两个表得出:直接对多维数组名进行加法操作,跨过的步长是该多维数组总大小的1\over n(n是数组的第一维数字)。那1\over n具体等于多少呢?

  设数组为b[n][o][p][q],则1\over n=o*p*q(参看上图的红字部分),即等于除第一维以外,剩下的所有维数大小之积。
  即这个多维数组的完全的大小也就是n*o*p*q

  下面将这个数组结构再次具象化一点,逐步从底层把这个数组构建起来。


  1、从最后一个维度看起,即 b[2][3][3][3] 的 [.][.][.][3]。假设没有前3个维度,那么这就是一个3个int构成的数据块,即 [.][.][.][3] int。图示如下:



  2、加入倒数第二个维度,即 b[2][3][3][3] 的 [.][.][3][3]。尝试这样理解:首先把最后一维数字先去掉,变成 [.][.][3][A]([A]=[3]int),此时整个数组为一个3xA大小的数据块。



  3、加入倒数第三个维度,即 b[2][3][3][3] 的 [.][3][3][3]。尝试这样理解:首先把最后的两个维数字先去掉,变成[.][3][B]([B]=[3][A]),此时整个数组为一个3xB大小的数据块。



  4、加入倒数第四个维度(即第一个维度),即 b[2][3][3][3] 的 [2][3][3][3]。尝试这样理解:首先把最后的两个维数字先去掉,变成[2][C]([C]=[3][B]),此时整个数组为一个2xC大小的数据块。

  至此,整个数组的大小已经完全构建了出来。大致可以显示如下:
  (注意这里每个格子的大小代表一个int,一般来说1个int占据4个内存单元,即4个Byte,所以每个格子之间的地址增量都是4)

  至此可能会有疑问:为什么int全落在的第四维的列上?事实是这样的么?用vs来验证一下:

    int b[2][3][3][3] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53 };

    int a[54] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53 };

    printf("%x\n", b);
    printf("%\n", a);

  通过对内存的查看,可以发现多维和单维的存储结构是完全一致的。



  现在分析一下数组名和指针的关系。经过上述,可知多维和单维存储结构完全一致,那么多维存在的概念如何理解?

  个人理解如下
  1、多维数组底层和单维数组完全一致。
  2、多维数组可以看作在单维之上,对原有的数组元素进行了“包装”,想要取得多维数组的元素,就行进行“拆包”(使用*或者[ ])。
  3、n维数组,就有n层“包装”,要取值必须“拆包”n次。

  首先看未“拆包”的情况下,b的指向情况。
  “拆包”1次。
  “拆包”2次。
  “拆包”3次。
  “拆包”4次。



  根据以上分析,分析下图白色框处,应该如何取值?

  按照图示,首先考虑下标法取值,各维度数值按照图示应该很好确定:
  1、第一维应该取0,因为白色块覆盖于第一维的橘色块下。
  2、第二维应该取2,因为白色块覆盖于第二维的黄色块下。
  3、第三维应该取2,因为白色块覆盖于第三维的橘色块下。
  4、第四维应该取0,因为白色块处于第三位的橘色块下的第一位置。
  综上:下标取值为:b[0][2][2][0]。

printf("b[0][2][2][0]=%d\n",b[0][2][2][0]);
b[0][2][2][0]=24

  可见输出结果与推测完全一致。



  按照图示,再次考虑“拆包”方式来取值。
  1、未拆包前,b不用加减,取原值。因为一旦加1,b指向的范围将超出白色块所在区域(指向第27处)。
  2、第一层“拆包”,为*b。等于*(b+0)。
  3、第二层“拆包”,为*(*(b+0)+2)。
  3、第三层“拆包”,为*(*(*(b+0)+2)+2)。
  4、第四层“拆包”,为*(*(*(*(b+0)+2)+2)+0)。

printf("*(*(*(*(b+0)+2)+2)+0)=%d\n",*(*(*(*(b+0)+2)+2)+0));
*(*(*(*(b+0)+2)+2)+0)=24


  推导结论:
  1、pass

  以下代码演示了使用多维数组名,以一维方式遍历数组元素的方式。

int b[2][3][3][3]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53};
printf("b[0][0][0][0]=%d\n",b[0][0][0][0]);
printf("b[0][0][0][1]=%d\n",b[0][0][0][1]);
printf("b[0][0][0][2]=%d\n",b[0][0][0][2]);
printf("b[0][0][1][0]=%d\n",b[0][0][1][0]);
printf("b[0][0][1][1]=%d\n",b[0][0][1][1]);
printf("b[0][0][1][2]=%d\n",b[0][0][1][2]);
printf("b[0][0][2][0]=%d\n",b[0][0][2][0]);
printf("b[0][0][2][1]=%d\n",b[0][0][2][1]);
printf("b[0][0][2][2]=%d\n",b[0][0][2][2]);
printf("b[0][1][0][0]=%d\n",b[0][1][0][0]);
printf("b[0][1][0][1]=%d\n",b[0][1][0][1]);
printf("b[0][1][0][2]=%d\n",b[0][1][0][2]);
printf("b[0][1][1][0]=%d\n",b[0][1][1][0]);
printf("b[0][1][1][1]=%d\n",b[0][1][1][1]);
printf("b[0][1][1][2]=%d\n",b[0][1][1][2]);
printf("b[0][1][2][0]=%d\n",b[0][1][2][0]);
printf("b[0][1][2][1]=%d\n",b[0][1][2][1]);
printf("b[0][1][2][2]=%d\n",b[0][1][2][2]);
printf("b[0][2][0][0]=%d\n",b[0][2][0][0]);
printf("b[0][2][0][1]=%d\n",b[0][2][0][1]);
printf("b[0][2][0][2]=%d\n",b[0][2][0][2]);
printf("b[0][2][1][0]=%d\n",b[0][2][1][0]);
printf("b[0][2][1][1]=%d\n",b[0][2][1][1]);
printf("b[0][2][1][2]=%d\n",b[0][2][1][2]);
printf("b[0][2][2][0]=%d\n",b[0][2][2][0]);
printf("b[0][2][2][1]=%d\n",b[0][2][2][1]);
printf("b[0][2][2][2]=%d\n",b[0][2][2][2]);
printf("b[1][0][0][0]=%d\n",b[1][0][0][0]);
printf("b[1][0][0][1]=%d\n",b[1][0][0][1]);
printf("b[1][0][0][2]=%d\n",b[1][0][0][2]);
printf("b[1][0][1][0]=%d\n",b[1][0][1][0]);
printf("b[1][0][1][1]=%d\n",b[1][0][1][1]);
printf("b[1][0][1][2]=%d\n",b[1][0][1][2]);
printf("b[1][0][2][0]=%d\n",b[1][0][2][0]);
printf("b[1][0][2][1]=%d\n",b[1][0][2][1]);
printf("b[1][0][2][2]=%d\n",b[1][0][2][2]);
printf("b[1][1][0][0]=%d\n",b[1][1][0][0]);
printf("b[1][1][0][1]=%d\n",b[1][1][0][1]);
printf("b[1][1][0][2]=%d\n",b[1][1][0][2]);
printf("b[1][1][1][0]=%d\n",b[1][1][1][0]);
printf("b[1][1][1][1]=%d\n",b[1][1][1][1]);
printf("b[1][1][1][2]=%d\n",b[1][1][1][2]);
printf("b[1][1][2][0]=%d\n",b[1][1][2][0]);
printf("b[1][1][2][1]=%d\n",b[1][1][2][1]);
printf("b[1][1][2][2]=%d\n",b[1][1][2][2]);
printf("b[1][2][0][0]=%d\n",b[1][2][0][0]);
printf("b[1][2][0][1]=%d\n",b[1][2][0][1]);
printf("b[1][2][0][2]=%d\n",b[1][2][0][2]);
printf("b[1][2][1][0]=%d\n",b[1][2][1][0]);
printf("b[1][2][1][1]=%d\n",b[1][2][1][1]);
printf("b[1][2][1][2]=%d\n",b[1][2][1][2]);
printf("b[1][2][2][0]=%d\n",b[1][2][2][0]);
printf("b[1][2][2][1]=%d\n",b[1][2][2][1]);
printf("b[1][2][2][2]=%d\n",b[1][2][2][2]);
   
 for(int i=0;i<(sizeof(b)/4);i++)
    {
        printf("****b+%d=%d\n",i,****b+i);
    }
b[0][0][0][0]=0
b[0][0][0][1]=1
b[0][0][0][2]=2
b[0][0][1][0]=3
b[0][0][1][1]=4
b[0][0][1][2]=5
b[0][0][2][0]=6
b[0][0][2][1]=7
b[0][0][2][2]=8
b[0][1][0][0]=9
b[0][1][0][1]=10
b[0][1][0][2]=11
b[0][1][1][0]=12
b[0][1][1][1]=13
b[0][1][1][2]=14
b[0][1][2][0]=15
b[0][1][2][1]=16
b[0][1][2][2]=17
b[0][2][0][0]=18
b[0][2][0][1]=19
b[0][2][0][2]=20
b[0][2][1][0]=21
b[0][2][1][1]=22
b[0][2][1][2]=23
b[0][2][2][0]=24
b[0][2][2][1]=25
b[0][2][2][2]=26
b[1][0][0][0]=27
b[1][0][0][1]=28
b[1][0][0][2]=29
b[1][0][1][0]=30
b[1][0][1][1]=31
b[1][0][1][2]=32
b[1][0][2][0]=33
b[1][0][2][1]=34
b[1][0][2][2]=35
b[1][1][0][0]=36
b[1][1][0][1]=37
b[1][1][0][2]=38
b[1][1][1][0]=39
b[1][1][1][1]=40
b[1][1][1][2]=41
b[1][1][2][0]=42
b[1][1][2][1]=43
b[1][1][2][2]=44
b[1][2][0][0]=45
b[1][2][0][1]=46
b[1][2][0][2]=47
b[1][2][1][0]=48
b[1][2][1][1]=49
b[1][2][1][2]=50
b[1][2][2][0]=51
b[1][2][2][1]=52
b[1][2][2][2]=53

****b+0=0
****b+1=1
****b+2=2
****b+3=3
****b+4=4
****b+5=5
****b+6=6
****b+7=7
****b+8=8
****b+9=9
****b+10=10
****b+11=11
****b+12=12
****b+13=13
****b+14=14
****b+15=15
****b+16=16
****b+17=17
****b+18=18
****b+19=19
****b+20=20
****b+21=21
****b+22=22
****b+23=23
****b+24=24
****b+25=25
****b+26=26
****b+27=27
****b+28=28
****b+29=29
****b+30=30
****b+31=31
****b+32=32
****b+33=33
****b+34=34
****b+35=35
****b+36=36
****b+37=37
****b+38=38
****b+39=39
****b+40=40
****b+41=41
****b+42=42
****b+43=43
****b+44=44
****b+45=45
****b+46=46
****b+47=47
****b+48=48
****b+49=49
****b+50=50
****b+51=51
****b+52=52
****b+53=53

  这里使用了4个

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343