1 一维度数组与指针
1.1一维数组元素在内存分布
-
#include<stdio.h> #include<stdlib.h> #include<string.h> #define ARRAY_SIZE 8 void main() { int data[ARRAY_SIZE]={0,1,2,3,4,5,6,7}; int i; printf("data address:0x%-8x\r\n",data); for(i=0; i<ARRAY_SIZE; i++) { printf("data[%-3d]:value %-3d,address:0x%-10x\r\n",i,data[i],&data[i]); } } data address:0xbc4100d0 data[0 ]:value 0 ,address:0xbc4100d0 data[1 ]:value 1 ,address:0xbc4100d4 data[2 ]:value 2 ,address:0xbc4100d8 data[3 ]:value 3 ,address:0xbc4100dc data[4 ]:value 4 ,address:0xbc4100e0 data[5 ]:value 5 ,address:0xbc4100e4 data[6 ]:value 6 ,address:0xbc4100e8 data[7 ]:value 7 ,address:0xbc4100ec
结论为:
1 数组元素的地址是线性的、连续的,这也是可以通过数组地址找到所有元素的原因。
2 数组名代表数组指针,同时与首元素的地址相同
1.2一维数组的指针
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define ARRAY_SIZE 8
void main()
{
int data[ARRAY_SIZE]={0,1,2,3,4,5,6,7};
int *pointer=data;
int i;
printf("data address:0x%-8x\r\n",data);
for(i=0; i<ARRAY_SIZE; i++)
{
printf("data[%d]:value %-3d,address:0x%-10x\r\n",i,data[i],&data[i]);
}
for(i=0; i<ARRAY_SIZE; i++)
{
printf("[%d]:value %-3d,address:0x%-10x\r\n",i,*(pointer+i),pointer+i);
}
}
data address:0x13bca160
data[0]:value 0 ,address:0x13bca160
data[1]:value 1 ,address:0x13bca164
data[2]:value 2 ,address:0x13bca168
data[3]:value 3 ,address:0x13bca16c
data[4]:value 4 ,address:0x13bca170
data[5]:value 5 ,address:0x13bca174
data[6]:value 6 ,address:0x13bca178
data[7]:value 7 ,address:0x13bca17c
[0]:value 0 ,address:0x13bca160
[1]:value 1 ,address:0x13bca164
[2]:value 2 ,address:0x13bca168
[3]:value 3 ,address:0x13bca16c
[4]:value 4 ,address:0x13bca170
[5]:value 5 ,address:0x13bca174
[6]:value 6 ,address:0x13bca178
[7]:value 7 ,address:0x13bca17c
结论为:
1 指向数组的指针加一表示加上每个元素的字节数
2 指针可以引用一个数组
2 二维度数组与指针
2.1 二维数组元素在内存分布
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define ARRAY_X 7
#define ARRAY_Y 5
void main()
{
int data[ARRAY_X][ARRAY_Y]={0};
int *pointer=data;
int i,j,k,num=0;;
for(i=0; i<ARRAY_X; i++)
{
for(j=0;j<ARRAY_Y;j++)
{
data[i][j]=num;
}
}
for(i=0; i<ARRAY_X;i++)
{
printf("\r\n");
for(j=0;j<ARRAY_Y;j++)
{
data[i][j]=num;
printf("data[%d][%d]:%d,(address:0x%-10x)\r\n",i,j,data[i][j],&data[i][j]);
}
}
}
data[0][0]:0,(address:0xfe8a3a10 )
data[0][1]:0,(address:0xfe8a3a14 )
data[0][2]:0,(address:0xfe8a3a18 )
data[0][3]:0,(address:0xfe8a3a1c )
data[1][0]:0,(address:0xfe8a3a20 )
data[1][1]:0,(address:0xfe8a3a24 )
data[1][2]:0,(address:0xfe8a3a28 )
data[1][3]:0,(address:0xfe8a3a2c )
data[2][0]:0,(address:0xfe8a3a30 )
data[2][1]:0,(address:0xfe8a3a34 )
data[2][2]:0,(address:0xfe8a3a38 )
data[2][3]:0,(address:0xfe8a3a3c )
root@ubuntu:Array#
通过实际的地址信息,可以知道:二维数组在内存中是连续发布的,第0行的第一个元素->第0行的最后一个元素->第1行的第1个元素->第1行的最后一个元素,以次类推,地址增长
2.2二维数组的指针
2.2.1指针的使用方法
声明一个二维数组 :int data[3][4]
1 根据”数组名同时是数组首元素的地址“的原则,data是首元素的地址,二维数组data[3][4]的首元素是一维数组,所以data是一维数组data[0]的地址
2 根据”数组名同时是数组首元素的地址“的原则,因此data的值等于&data[0],data[0]表示数组data[3][4]的首元素,这个首元素也是数组。根据“数组名同时是数组首元素的地址”的原则,data[0] 等于&data[0][0]
3 根据“指针加1等于加上指针所指向的元素的大小“的原则,data+1并不等于data[0]+1,前者是4个单位,后者是1个单位“
4 对一个指针取值得到的是该指针所指向对象的数值。data[0]表示一维数组data[0]的首元素即data[0][0]的地址,则*(data[0])表示元素data[0][0]的值
2.2.2 指针、指针的指针、变量
声明一个二维数组 :int data[3][4]
本例中,哪些是一维数组指针,哪些是二维数组指针,哪些是元素值?
二维数组指针:data
一维数组指针:data[0]、data[1]、data[2]
元素值:data[0][0]、data[0][1]、data[0][2]、data[0][3]
c语言中,*号表示取值,&号表示取地址,按照原则,可以知道:
data 是二维数组指针,*data是二维数组的元素即一维数组data[0];data[0]表示一维数组的地址,data[0]就表示一位数组data[0]首元素data[0][0]的地址。所以 **data的值就是data[0][0],data的值就是&&data[0][0]
注意:比较简单的方法是,将指针转化为数组来理解,例如*(*(pointer+i)+j)的代码写成pointer[i][j],减少出错的概率,[]表示偏移后取值
2.2.3 使用二维数组指针去访问元素
声明一个二维数组 :int data[3][4],data代表这个二维数组的指针
data | 第一个元素的地址,该元素是一维数组 |
data+1 | 第二个元素的地址,该元素是一维数组 |
*(data+1) | 数组的地址,也是数组的首元素的地址,该数组是一维数组。*(data+1)的值于data+1相同,但是意义不一样。 |
(*(data+1)+2) | 二维数组第1行第2列的元素的地址,也是一位数组data+1的第2个元素的地址。 |
*(*(data+1)+2) | 二维数组第一行第二列元素的值 |
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define ARRAY_X 3
#define ARRAY_Y 4
void main()
{
int data[ARRAY_X][ARRAY_Y]={0};
int *pointer=data;
int i,j,k,num=10;;
for(i=0; i<ARRAY_X; i++)
{
for(j=0;j<ARRAY_Y;j++)
{
data[i][j]=num++;
}
}
for(i=0; i<ARRAY_X;i++)
{
printf("\r\n");
for(j=0;j<ARRAY_Y;j++)
{
printf("data[%d][%d]:%d,(address:0x%-10x)\r\n",i,j,data[i][j],&data[i][j]);
}
}
printf("data:0x%x\r\n",data);
printf("*data:0x%x\r\n",*data);
printf("**data:0x%x\r\n",**data);
printf("data[0][0]:0x%x\r\n",data[0][0]);
printf("&data[0][0]:0x%x\r\n",&data[0][0]);
printf("data[0]:0x%x\r\n",data[0]);
printf("&data[0]:0x%x\r\n",&data[0]);
printf("&data[0][0]:0x%x\r\n",&data[0][0]);
for(i=0; i<ARRAY_X;i++)
{
printf("\r\n");
for(j=0;j<ARRAY_Y;j++)
{
printf("*(data+%d)):0x%x\r\n",i,*(data+i));
printf("*(*(data+%d)+%d):%d\r\n",i,j,*(*(data+i)+j));
}
}
}
data[0][0]:10,(address:0xf49fe5e0 )
data[0][1]:11,(address:0xf49fe5e4 )
data[0][2]:12,(address:0xf49fe5e8 )
data[0][3]:13,(address:0xf49fe5ec )
data[1][0]:14,(address:0xf49fe5f0 )
data[1][1]:15,(address:0xf49fe5f4 )
data[1][2]:16,(address:0xf49fe5f8 )
data[1][3]:17,(address:0xf49fe5fc )
data[2][0]:18,(address:0xf49fe600 )
data[2][1]:19,(address:0xf49fe604 )
data[2][2]:20,(address:0xf49fe608 )
data[2][3]:21,(address:0xf49fe60c )
data:0xf49fe5e0
*data:0xf49fe5e0
**data:0xa
data[0][0]:0xa
&data[0][0]:0xf49fe5e0
data[0]:0xf49fe5e0
&data[0]:0xf49fe5e0
&data[0][0]:0xf49fe5e0
*(data+0)):0xf49fe5e0
*(*(data+0)+0):10
*(data+0)):0xf49fe5e0
*(*(data+0)+1):11
*(data+0)):0xf49fe5e0
*(*(data+0)+2):12
*(data+0)):0xf49fe5e0
*(*(data+0)+3):13
*(data+1)):0xf49fe5f0
*(*(data+1)+0):14
*(data+1)):0xf49fe5f0
*(*(data+1)+1):15
*(data+1)):0xf49fe5f0
*(*(data+1)+2):16
*(data+1)):0xf49fe5f0
*(*(data+1)+3):17
*(data+2)):0xf49fe600
*(*(data+2)+0):18
*(data+2)):0xf49fe600
*(*(data+2)+1):19
*(data+2)):0xf49fe600
*(*(data+2)+2):20
*(data+2)):0xf49fe600
*(*(data+2)+3):21
2.2.4 指向二维数组的指针
在编写函数时,入参通常会是一个二维数组的指针,怎样正确访问这个二维数组的指针呢?
声明一个二维数组 :int data[3][4]。
声明一个指针int (* pointer)[4],该指针指向一个包含4个元素的数组.
[4]通知编译器,每次pointer+1将会移动4个单位的长度。
错误的声明:int ** pointer,等价于int (* pointer)[1],编译器不知道宽度,每次pointer+1只会移动1个单位的长度
错误的声明:int * pointer[4],变成了指针数组,指针指向整型数。
void main()
{
int data[ARRAY_X][ARRAY_Y]={0};
int (*pointer)[ARRAY_Y]=data;
int i,j,k,num=10;;
for(i=0; i<ARRAY_X; i++)
{
for(j=0;j<ARRAY_Y;j++)
{
data[i][j]=num++;
}
}
for(i=0; i<ARRAY_X;i++)
{
printf("\r\n");
for(j=0;j<ARRAY_Y;j++)
{
printf("data[%d][%d]:0x%x,(address:0x%-10x)\r\n",i,j,data[i][j],&data[i][j]);
}
}
printf("data:0x%x\r\n",data);
printf("*data:0x%x\r\n",*data);
printf("**data:0x%x\r\n",**data);
printf("data[0][0]:0x%x\r\n",data[0][0]);
printf("&data[0][0]:0x%x\r\n",&data[0][0]);
printf("data[0]:0x%x\r\n",data[0]);
printf("&data[0]:0x%x\r\n",&data[0]);
printf("&data[0][0]:0x%x\r\n",&data[0][0]);
for(i=0; i<ARRAY_X;i++)
{
printf("\r\n");
for(j=0;j<ARRAY_Y;j++)
{
printf("*(pointer+%d)+%d: 0x%x\r\n",i,j, *(pointer+i)+j);
printf(" *(*(pointer+%d)+%d): 0x%x\r\n",i,j, *(*(pointer+i)+j));
}
}
}
data[0][0]:0xa,(address:0xb8a93be0 )
data[0][1]:0xb,(address:0xb8a93be4 )
data[0][2]:0xc,(address:0xb8a93be8 )
data[0][3]:0xd,(address:0xb8a93bec )
data[1][0]:0xe,(address:0xb8a93bf0 )
data[1][1]:0xf,(address:0xb8a93bf4 )
data[1][2]:0x10,(address:0xb8a93bf8 )
data[1][3]:0x11,(address:0xb8a93bfc )
data[2][0]:0x12,(address:0xb8a93c00 )
data[2][1]:0x13,(address:0xb8a93c04 )
data[2][2]:0x14,(address:0xb8a93c08 )
data[2][3]:0x15,(address:0xb8a93c0c )
data:0xb8a93be0
*data:0xb8a93be0
**data:0xa
data[0][0]:0xa
&data[0][0]:0xb8a93be0
data[0]:0xb8a93be0
&data[0]:0xb8a93be0
&data[0][0]:0xb8a93be0
*(pointer+0)+0: 0xb8a93be0
*(*(pointer+0)+0): 0xa
*(pointer+0)+1: 0xb8a93be4
*(*(pointer+0)+1): 0xb
*(pointer+0)+2: 0xb8a93be8
*(*(pointer+0)+2): 0xc
*(pointer+0)+3: 0xb8a93bec
*(*(pointer+0)+3): 0xd
*(pointer+1)+0: 0xb8a93bf0
*(*(pointer+1)+0): 0xe
*(pointer+1)+1: 0xb8a93bf4
*(*(pointer+1)+1): 0xf
*(pointer+1)+2: 0xb8a93bf8
*(*(pointer+1)+2): 0x10
*(pointer+1)+3: 0xb8a93bfc
*(*(pointer+1)+3): 0x11
*(pointer+2)+0: 0xb8a93c00
*(*(pointer+2)+0): 0x12
*(pointer+2)+1: 0xb8a93c04
*(*(pointer+2)+1): 0x13
*(pointer+2)+2: 0xb8a93c08
*(*(pointer+2)+2): 0x14
*(pointer+2)+3: 0xb8a93c0c
*(*(pointer+2)+3): 0x15
3 指针的指针的指针
3.1 指向二维数组的指针--元素为基本类型
声明一个二维指针数组:int * p_data[3][4]
这是一个二维数组,数组元素中存放的是指针,指针指向一个整型数。
int *(*pointer)[4]
这是一个指针,指向一个一维数组,该一维数组长度为4,数组的每个元素是一个指向整型数的指针。
如何使用 pointer来访问p_data的值呢?
pointer=p_data;
p_data[i][j] 等价于pointer[i][j],等价于*(*(pointer+i)+j) ;
*(p_data[i][j])等价于*(pointer[i][j],等价于 **(*(pointer+i)+j)
3.2 指向二维数组的指针--元素为结构体
声明结构体
typedef struct avl{
int name[4];
int age;
}AVL;
定义宏
#define ARRAY_X 3
#define ARRAY_y 6
声明二维结构提指针数组
AVL* pointer[ARRAY_X][ARRAY_y];
声明指向数组的指针,数组的长度为6,每个元素为存放AVL类型指针
AVL*(*ppp)[ARRAY_y];
ppp=pointer;
引用方法:
ppp[x][y]
ppp[x][y])->name
ppp[x][y])->age
二维数组指针的关键是数组的宽度,告诉编译器每次移动一个单位需要偏移多少个字节。