一、数组指针访问元素
-
直接通过例题去理解一维二维三维数组指针如何访问指向的数据类型中的元素的
#include "stdafx.h" char data[] = { //定义一个一维数组 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x07,0x09, 0x00,0x20,0x10,0x03,0x03,0x0C,0x00,0x10,0x44,0x00, 0x00,0x33,0x00,0x47,0x0C,0x0E,0x00,0x0D,0x00,0x11, 0x00,0x00,0x00,0x02,0x64,0x00,0x00,0x00,0xAA,0x00, 0x00,0x00,0x64,0x10,0x00,0x00,0x00,0x00,0x70,0x00, 0x10,0x20,0x02,0x00,0x74,0x0F,0x41,0x00,0x00,0x00, 0x01,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x0A,0x00, 0x00,0x02,0x74,0x0F,0x41,0x00,0x06,0x08,0x00,0x00, 0x00,0x00,0x00,0x64,0x00,0x0F,0x00,0x00,0x0D,0x00, 0x00,0x00,0x23,0x00,0x00,0x64,0x00,0x00,0x64,0x00 }; int main(int argc,char* argv[]){ //一维数组指针 int (*px)[5]; //定义一个int (*)[5]类型的数组指针px px = (int (*)[5])data; //让此数组指针指向data数组,去操作数组中的元素 printf("%x\n",*(*(px+2)+2)); //因为px类型为int (*)[5],去掉一个*,类型为int [5],宽度为4*5=20,所以px+2相当于地址加了2*20=40 字节,而*(px+2)的类型为int [5]类型,所以*(px+2)表示的含义就是px最初的地址+40字节后的地址; 再算 *(px+2)+2,因为*(px+2)的类型为int [5],去掉一个*号后的类型为int类型,宽度为4,所以*(px+2)+2相当 于地址又加了4*2=8字节,而*(*(px+2)+2)的类型为int类型,所以*(*(px+2)+2)表示的含义就是取在px的地 址偏移了40字节后再偏移8字节最终得到的地址中的元素,且取4字节宽度作为最终的结果值.因为px指向的是char 类型的data数组,一个元素1字节,所以相当于从第一个元素往后数48个的元素的地址开始往后数4字节,把这个值取出来,而因为这4个字节在内存中是倒着以1字节为单位从低地址往高地址存的,那么70 00 10 20最后要读作 0x20100070 char (*px1)[3]; //还可以定义char (*px1)[3]类型的数组指针 px1 = (char (*)[3])data; //同样可以去操作data数组中的数据 printf("%x\n",*(*(px1+4)+5)); //地址 + 1*3*4 + 1*5 = 地址+17字节,即第18个元素地址开始往后取 1字节宽度的值,即0x10 //二维数组指针 int (*py)[2][3]; //定义int (*)[2][3]类型的二维数组指针py py = (int (*)[2][3])data; //py指向data数组首地址 printf("%x\n",*(*(*(py+2)+2)+2)); //因为一维数组指针访问元素需要两个*,那么二维就需要三个*才能访问到。还是按照从里往外分析,因为py是int (*)[2][3]类型,去掉一个*号后的类型为int [2][3],宽度为2*3*4,所以py+2相当于从py的初始地址+ 2*3*4 * 2,即*(py+2)最终得到的结果是初始地址+48后的地址;接着再分析*(py+2)+2,因为*(py+2)类型为int [2][3],去掉一个*号后的类型为int [3]类型,宽度为3*4,所以*(py+2)+2相当于此时的地址 + 3*4 * 2 = 24,即*(*(py+2)+2)最终得到的结果是初始地址+48再+24后的地址;最后分析*(*(py+2)+2)+2,因为*(*(py+2)+2)的类型为int [3]类型,去掉一个*号后的类型为int类型,所以*(*(py+2)+2)+2相当于此时的地址 + 4*2,即*(*(*(py+2)+2)+2))最终得到的即结果是取初始地址+48再+24再+8后的地址中的值,由于*(*(*(py+2)+2)+2))的类型为int型,所以取的值是最终得到的地址往后取4字节宽度的值,也就是 00 00 00 64,内存中的数据是以1字节为单位从低地址向高地址反着存的,所以我们最后应该读作0x64000000 //三维数组指针 char (*pz)[2][3][2]; pz = (char (*)[2][3][2])data; printf("%x\n",*(*(*(*(pz+2)+2)+2)+2)); //从内往外分析地址+了多少: //2*3*2*1 * 2 = 24 | 3*2*1 * 2 = 12 | 2*1 * 2 = 4 | 1 * 2 = 2 //所以最终地址+了24 + 12 + 4 + 2 = 42,因为数组是char类型,一个元素1字节,所以相当于第一个元素+42 个元素处,向后取1字节宽度的数据,即0x64 //注意char (*)[2][3][2]去掉一个*号类型为char [2][3][2]类型,宽度为2*3*2*1=12字节;再去掉一个*号 类型为char[3][2],宽度为3*2*1=6字节;再去掉一个*号类型为char[2]!宽度为2*1=2字节;再去掉一个*号类 型为char类型!宽度为1字节 }
一定要理解:不是一维数组指针就是专门指向一维数组的而且还是同样长度的。一维数组指针可以访问一维数组,还可以访问二维和三维数组,也可以访问其他类型的数据;同理二维数组也可以访问一维、二维、三维数组、其他类型数据等。数组指针
[]
里的数组也可以是任意的。用不同的数组指针去访问不同的数组,目的都是使用数组指针去操作数组中的元素,不同点在于不同的数组指针在做运算时的结果不同:比如使用char (*px)[5]
,宽度为4,但是它在做++/–/+整数最终要偏移的步长是根据去掉一个*
号决定的,即char [5]
,那么宽度就为5*1,如果指针做+4操作,就是5*1*4 = 20
;那么如果使用int (*px)[3]
,那么此指针做+4操作,就是3*4*4 = 48
。所以当我们使用这些不同的指针去获取不同的元素时(比如(*(px+4)+2)
),步长是不同的,所以定义一个合适的指针去访问可以事半功倍,而且我们可以根据我们的需求去选择何时的指针 -
不管是一维数组、二维数组还是三维数组本质上他们的数据在内存中都是一维的形式存储的
int arr[2][3] = {{1,2,3},{4,5,6}};