内容介绍:
一、二维数组的定义
二、指针数组和数组指针
三、数组指针
一、二维数组的定义
在c语言中,并没有真正意义上的二维数组,二维数组只是简单的通过线性方式进行扩展的,如下图:
这个二维数组事实上就是定义4个元素的一维数组,然后每个元素都是包含五个整型变量的一维数组,所以在内存中仍然是有一个线性方式进行存储的
假设定义了二维数组array[4][5]
Array是二维数组的首地址,在整个数组中,数组名就是第一个元素的指针,也就是地址,由于二维数组实际上是一维数组的扩展,所以array可以理解为:指向包围五个元素的数组的指针。
证明案例:
#include <stdio.h>
int main( )
{
char str[] = "I Love FishC. com!" ;
char *target = str ;
int count =0;
while (*target++ != '\0')
{
count++ ;
}
printf("总共有%d个字符! \n", count);
return 0 ;
}
结论:数组名只是一个地址,而指针是一个左值。
#include <stdio .h>
int main()
{
int array[4][5] = {0};
//打印出整型所占用的空间
printf("sizeof int: %d\n", sizeof(int));
//打印出array的地址(二维数组首地址)
printf("array: 8p\n “,array) ;
//打印array+1的值(地址)
printf( " array+1:%p\n",array +1);
return 0 ;
}
运行:gcc testl.c && ./a. out
结果:
sizeof int: 4
array: 0xbfc34320
array+1:0xbfc34334
结论:两个地址相减就能知道跨度是多少
*(array+1)表示:
l 指向第二行子数组第一个元素的指针
l Array+1同样也是指向五个元素数组的地址
l *(array+1)=array[1],因为左边是右边的语法谈(添加一个新的功能方便程序员的使用),使用array[1]这个会便捷轻松许多
解引用:把一个地址的值取出来
修改代码:
#include <stdio. h>
int main( )
{
//赋不一样的初值
int array[4][5] = {0};
int i,j,k=0;
//双重循环
for(i=0;i<4;i++)
{
for(j=0;j<5;j++)
{
array[i][j] = k++;
}
}
//打印array+1
printf("*(array+1): %p\n", *(array + 1));
//打印语法谈
printf("array[1]: %p\n", array[1]) ;
//打印第一个元素的地址
printf("&array[1][0]: %p\n", &array[1][0]);
//双重解引用,元素申明整形
printf("**(array+1): %d\n", **(array + 1));
return 0;
}
运行:gcc test2.c && ./a. out
结果:
*(array+1) : 0xbfaa1518
array[1]: Oxbfaa1518
&array[1][0]: 0xbfaa1518
**(array+1):5
结论:发现地址都是一样的,都是5,两个地址相减就能知道跨度是多少
*(*(array+1)+3)表示:
- 指向第二行子数组第4个元素的指针
验证案例修改代码:
#include <stdio. h>
int main( )
{
//赋不一样的初值
int array[4][5] = {0};
int i,j,k=0;
//双重循环
for(i=0;i<4;i++)
{
for(j=0;j<5;j++)
{
array[i][j] = k++;
}
}
//打印array+1
printf("*(array+1): %p\n", *(array + 1));
//打印语法谈
printf("array[1]: %p\n", array[1]) ;
//打印第一个元素的地址
printf("&array[1][0]: %p\n", &array[1][0]);
//双重解引用,元素申明整形
printf("**(array+1): %d\n", **(array + 1));
//进行解引用
printf("*(*(array+1)+3): %p\n",*(*(array+1)+3));
//打印地址值
printf("&array[1][3]: %d\n", &array[1][3]);
return 0;
}
运行:gcc test2.c && ./a. out
结果:
*(array+1) : 0xbfaa1518
array[1]: Oxbfaa1518
&array[1][0]: 0xbfaa1518
**(array+1):5
*(*(array+1)+3):8
array[1][3]:8
结论:无论是二维数组还是多维数组,都可以用这种间接引用的方式来实现,下标形式都可以转换为指针形式
二、 指针数组和数组指针
二维数组的初始化也能偷懒,让编译器根据元素的数量计算数组的长度。但只有第1维的元素个数可以不写,其他维度必须写上:不然就会报错。
int a[][4] = {1,2, 3,4},{5, 6,7,8},{9,10,11,12}];
这种可以
int a[][] = {1,2, 3,4},{5, 6,7,8},{9,10,11,12}];
这种就会报错
定义一个数组指针是这样的:int (*p)[3];
解释语句:int (*p)[3] = array;
*p也可以赋值给array,都是数组指针
验证案例:
#include <stdio.h>
int main()
{
//定义二维数组
int array[2][3]= {{0,1,23,{3.4,5}};
//定义指向三个元素的数组
int(*p)[3] = array;
//打印出结果,看这索引方式的值是否一样
printf("**(p+1) :%d\n"",**(p+1));
printf("**(array+l):%d/n",**(arrayt1));
printf( "array[1][0]:%d\n", array[1][0]);
printf("*(*(p+1)+2) :%d\n"",*(*(p+1)+2));
printf("*(*(array+l)+2):%d/n",*(*(array+l)+2));
printf( "array[1][2]:%d\n", array[1][2]);
return 0;
}
结果:运行gcc test4.c && ./a.out
**( p+1):3
*(array+l):3
array [1][0]:3
*(*(p+1)+2):5
*(*(array+1)+2):5
array[1][2]: 5
结论:三种方式进行索引,值都是一样的