一维数组:int ara[3]={1,2,3};
printf("%d\n",ara):
printf("%d\n",&ara):
打印之后,发现ara和&ara两个值是一样的,为什么?
按照我们学习的理解,&ara是取ara的地址,一个是地址,一个是值,不应该一样,那为什么打印出来会是一样的?
从汇编的角度可以解释这个问题:
printf("%d\n",ara):
printf("%d\n",&ara):
会发现取得值都是lea eax,[ebp-4],说明在堆栈中就没有为ara这个变量分配空间(如果分配空间了,&ara和ara这两个值肯定不一样)
因此,数组名这个变量和普通的变量不一样,普通的局部变量如果定义之后,函数调用的时候,会在堆栈,一般会是[ebp-xx]的位置为这个变量分配一个空间
而数组名,则是直接使用ebp-xx这个值的,这样从反汇编的角度就解释了,为什么这2个值是一样的。
CPU的世界里,只认识0和1,虽然这个值是一样的,但是这个2个值的类型是不一样的,可以赋值给ara=4,&ara=5,编译器会报错,给出我们答案。
ara 是int[3]类型 数组第一个值的地址。
&ara是int (*)[3]类型,指针数组,后边会解释这种类型。 把数组当成一个整体,整个数组的地址。
就像前边学的进制一样,0xFF,当做有符号数就是-1,无符号数就是255.但是CPU可不管你是多少,就是一堆0和1,只有使用的程序员才关心类型,同一个值,不同的类型。
ara + N是多少呢,可以用前边学的指针解释吗?
可以, ara是数组第一个值的地址,当做short* ara[0]
ara + N = ara + N*(short宽度)
二维数组:
int arr[3][5]={
{1,2,3,4},
{5,6,7,8},
{9,10,11,12}
};
arr ,&arr, *arr 这三个值都一样,理解为整体和局部的关系:
整体:
&arr是数组指针, int (*)[3][5]类型,也是第一个元素的地址(把数组当成一个整体看待,这个地址就是这个整体的地址)。
&arr+N = arr + N*3*5*int宽度
&arr-N = arr - N*3*5*int宽度
局部1:
*arr 宽度为:int的宽度×(第二维数字,5),值为指向数组中第一组数组的地址,第一组数据是{1,2,3,4},这个的地址。
*arr 是int[5]类型
*arr + N = arr + N*(int宽度)
*arr - N = arr - N*(int宽度)
arr是int [3][5]类型,宽度是3*5*4=60,值为指向第一个元素的地址
arr + N = arr + N*(第二维数字,5)*(int宽度)
arr - N = arr - N*(第二维数字,5)*(int宽度)
多维数组的理解实例:
short code[]={
0x9e,0x0a,0xc1,0x75,0x82,0xaad9,0xaa,0x2b,0x76,0x39, //1*20
0x50,0xc4,0x2a,0xf4,0xba,0x2c,0xe5,0xa3,0xe4,0x0f, //2*20
0xa9,0x5d,0x42,0xf2,0x37,0xe8,0xc6,0x3f,0x27,0xf1, //3*
0x48,0xc7,0x45,0x8e,0x44,0xe0,0x91,0xe9,0xc8,0x90, //4*20
0x7c,0xab,0x74,0xbe,0x43,0x0d,0x0d,0x17,0x6b,0x1b, //5
0xaa,0x81,0x8c,0xa1,0x66,0x79,0xec,0x53,0xf3,0xa6, //6
0x3e,0x8a,0xe0,0x84,0x56,0x39,0xad,0x60,0x65,0x7d, //7*20
0xe0,0xb1,0x83,0x77,0xe6,0x97,0xbb,0x84,0x06,0x83, //8*20
0x60,0xb9,0xa1,0x90,0x83,0x8c,0xfb,0xbf,0x0d,0x2f, //9*20
0xeed0,0x5d,0x24,0x7e,0x35,0xd2,0x9d,0x7a,0xde,0xe0, //10*20
0x9e,0x0a,0xc1,0x75,0x82,0xd9,0x3d,0x2b,0x76,0x39,
0x50,0xc4,0x2a,0xf4,0xba,0x2c,0xe5,0xa3,0xe4,0x0f,
0xa9,0x5d,0x42,0xf2,0x37,0xe8,0xc6,0x3f,0x27,0xf1, //13*20
0x48,0xc7,0x45,0x8e,0x44,0xe0,0x91,0xe9,0xc8,0x90,
0x7c,0xab,0x74,0xbe,0x43,0x0d,0x0d,0x17,0x6b,0x1b, //15*20=300
0xaa,0x81,0x8c,0xa1,0x66,0x79,0xec,0x53,0xf3,0xa6, //16*20=320
0x3e,0x8a,0xe0,0x84,0x56,0x39,0xad,0x60,0x65,0x7d, //8400e0
0xe0,0xb1,0x83,0x77,0xe6,0x97,0xbb,0x84,0x06,0x83,
0x60,0xb9,0xa1,0x90,0x83,0x8c,0xfb,0xbf,0x0d,0x2f,
0xd0,0x5d,0x24,0x7e,0x35,0xd2,0x9d,0x7a,0xde,0xe0, //20*20
0x9e,0x0a,0xc1,0x75,0x82,0xd9,0x3d,0x2b,0x76,0x39,
0x50,0xc4,0x2a,0xf4,0xba,0x2c,0xe5,0xa3,0xe4,0x0f,
0xa9,0x5d,0x42,0xf2,0x37,0xe8,0xc6,0x3f,0x27,0xf1,
0x48,0xc7,0x45,0x8e,0x44,0xe0,0x91,0xe9,0xc8,0x90,
0x7c,0xab,0x74,0xbe,0x43,0x0d,0x0d,0x17,0x6b,0x1b,
0xaa,0x81,0x8c,0xa1,0x66,0x79,0xec,0x53,0xf3,0xa6,
0x3e,0x8a,0xe0,0x84,0x56,0x39,0xad,0x60,0x65,0x7d,
0xe0,0xb1,0x83,0x77,0xe6,0x97,0xbb,0x84,0x06,0x83,
0x60,0xb9,0xa1,0x90,0x83,0x8c,0xfb,0xbf,0x0d,0x2f,
0xd0,0x5d,0x24,0x7e,0x35,0xd2,0x9d,0x7a,0xde,0xe0,
0x9e,0x0a,0xc1,0x75,0x82,0xd9,0x3d,0x2b,0x76,0x39,
0x50,0xc4,0x2a,0xf4,0xba,0x2c,0xe5,0xa3,0xe4,0x0f,
0xa9,0x5d,0x42,0xf2,0x37,0xe8,0xc6,0x3f,0x27,0xf1,
0x48,0xc7,0x45,0x8e,0x44,0xe0,0x91,0xe9,0xc8,0x90,
0x7c,0xab,0x74,0xbe,0x43,0x0d,0x0d,0x17,0x6b,0x1b,
0xaa,0x81,0x8c,0xa1,0x66,0x79,0xec,0x53,0xf3,0xa6,
0x3e,0x8a,0xe0,0x84,0x56,0x39,0xad,0x60,0x65,0x7d,
0xe0,0xb1,0x83,0x77,0xe6,0x97,0xbb,0x84,0x06,0x83,
0x60,0xb9,0xa1,0x90,0x83,0x8c,0xfb,0xbf,0x0d,0x2f,
0xd0,0x5d,0x24,0x7e,0x35,0xd2,0x9d,0x7a,0xde,0xe0 //40
};
unsigned char (*p1)[3];
unsigned short (*p2)[7];
int (*p3)[9];
p1 = (unsigned char (*)[3])code;
p2 = (unsigned short (*)[7])code;
p3 = (int (*)[9])code;
printf("%x,%x\n",code[1],code[5]);
printf("%x,%x\n",*(*(p1)+10),code[5]);//p1+10=0x00d9
printf("%x,%x\n",*(*(p1+5)+9),code[12]);//p1 + 3*5*1+9=24,2a
printf("%x,%x\n",*(*p2+5),code[5]);//p2+5*2,0xd9
printf("%x,%x\n",*(*(p2+5)+7),code[42]);//p2+5*7*2+7*2=84,0x74
printf("%x,%x\n",*(*p3+3),code[6]);//p3+12=0x2b00aa
printf("%x,%x\n",*(*(p3+7)+3),code[132]);//p3+7*9*4+3*4=264,8e0045
int (*px)[4][3][5];
unsigned char (*py)[3][5][6];
px =(int (*)[4][3][5])code;
py = (unsigned char (*)[3][5][6])code;
printf("%x,%x\n",*(*(*(*(px+1)+1)+1)+1),code[162]);
printf("%x,%x\n",*(*(*(*(px+1)+1)+1)+1),code[162]);//px+1*4*3*5*4 + 1*3*5*4 + 1*5*4 + 1*4 =324,8400e0
printf("%x,%x\n",*(*(*(*(py+2)+3)+4)+6),code[150]);//py+2*3*5*6*1 + 3*5*6*1 + 4*6*1 + 6*1=300,aa
类型N (*px)[i][j][k]
*(*(*(*(px+X)+Y)+Z)+M)=p的地址+p去掉*号的类型×X×类型N + Y×(*p的类型)×类型N + Z*(**p的类型)× 类型N + M*类型N = p的地址 + X×i×j×k×类型N + Y×j×k×类型N + Z×k×类型N+ M*类型N 。注意取出来的值是类型N。
理解方法:
px是类型N (*)[i][j][k]类型,是指向类型N [i][j][k]数组的指针,px+X,就是加上去掉*号的类型乘以X,去掉*号的类型是类型N [i][j][k],因此是加上px + X*i*j*k*类型N
*(px + X),取*之后类型就由整个3维数组的地址转换为指向2维数组的地址,就变成了指向(类型N (*)[j][k])的类型,即因此去掉*号之后就是(类型N [j][k])的数组地址类型,因此*(px + X)+ Y,就是加上Y*j*k*类型N;
*(*(px + X)+Y) ,取*之后类型之后,就变成了(类型N (*) [k])的类型,即指向(类型N [k])的数组地址,因此*(*(px + X)+Y)+Z,就是加上z*k*类型N;
*(*(*(px + X)+Y)+Z) 取*之后,类型就变成了指向数组第一个元素的地址,因此加*(*(*(px + X)+Y)+Z) + M,加的得就是加上M×去掉*号的类型,即M*类型N
*(*(*(*(px + X)+Y)+Z) + M),再取*号,就是取出这个地址的值。
可以理解为由整体的三维数组到数组中变量的地址转换,每次*号一次就是一次类型变化。
标签:精通,code,int,px,arr,ara,数组,类型,指针 From: https://www.cnblogs.com/gusseMe/p/17495644.html