问题描述:于习题中碰到关于数组传递的问题,不熟悉相关。引发运行错误
//二维数组传递的几种方式
(1) void function(char a[][20]) //数组名传递
{
}
(2) void function(char *p[]) // 指针数组传递
{
}
(3) void function(char (*p)[20]) //数组指针传递
{
}
#include
void function(char a[][10])
{
for(int i = 0 ;i < 4; i++)
{
printf(" %s /n", a[i]);
printf(" %c /n", a[i][2]); // 每行输出最后一个元素
}
printf(" %s /n", a[i]); //越界访问
}
void function2(char *p[])
{
for(int i = 0; i < 4; i++)
{
printf(" %s /n", *p++);
printf(" %c /n", *(*p +2)); // 每行输出最后一个元素
}
printf(" %s /n", *p++); //越界访问
}
void function3(char (*p)[10])
{
for(int i = 0; i < 4; i++)
{
printf(" %s /n", *p++);
printf(" %c /n", *(*p +2)); // 每行输出最后一个元素
}
printf(" %s /n", *p); //越界访问
}
void main()
{
printf("test for parameters/n");
char a[][10] = {"sat", "sun", "mon", "tue"} ;
char *p[] = {*a, *(a+1), *(a+2), *(a+3)} ;
//a[][10]
printf("============a[][10]==========/n ");
function(a);
//*p[]
printf("==========*p[]============/n ");
function2(p);
//(*p)[10]
printf("==========(*p)[10]============/n ");
function3(a);
}
分析:
去调越界访问语句后, 三种方式输出都是一样 完全正常,
从本质意义上来将*p[] 和 (*p)[10] 其实应该是一样的。*p[]比较麻烦,因为还要把各行的地址初始化给它。
*p[] 指针的数组 每个元素指向数组的指针,经过初始化后 存放的是二维数组中行的地址。P++后指向都是下一行的地址;
(*p)[10] 数组的指针 p指向一个含有十个元素的数组 ,因为指向了a的第一行 所以p++按照指针变量的运算,(指向下一个变量的地址),也就是指向了下一行的地址(这里的变量就成了a的一行)。如果说a只有一行,那么p++肯定是要越界了
关于越界:
char a[][10] 和 (*p)[10] 中因为传递的都是数组的指针, 该数组存储空间位于栈上,所以当地址越界 p++后 指向的是栈中的莫名元素,故输出乱码,程序却不会崩溃。而且二者的输出内容也是完全一致的。
同时*p[] 中被初始化为各行的首地址, p++越界后,指针变量p 也是位于栈上,关键是还有一个运算*p ,(p越界后其内容是随机的 *p之后指向随机的内存 而不是像(*p)[10]那样还是指在栈空间), 故程序输出崩溃。
再进一步 数组寻址跟指针寻址本质上还是一样的。2 和3 函数其实都是可以写成数组方式的形式的: *(*(p + i ) + j ) 访问数组中a[i][j]元素。
三者的共同不方便处,函数内部都无法知道数组维数大小(指针传递的不方便处)。可以增加想关的维数变量来解决这个问题。