版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/jeffscott/article/details/79090705
一、概念明确
指针数组,是指一个数组中存放的元素是某种类型的指针,二维数组本质上是两个一维数组的合成。当在定义二维数组时,就已经分配给二维数组空间,但是定义一个指针数组,指针数组里面的指针却不会自动初始化,此时的指针仍然是野指针,这时不能直接对其赋值。
二、代码阐释
1)打印验证
#include<stdio.h>
#include<string.h>
int main()
{
char A[3][5];//定义二维数组,未初始化
char *B[3];//定义指针数组,未初始化
int i=0;
printf("二维数组的指针:\n");
for(i=0;i<3;i++)
printf("%p\n",A[i]);//打印二维数组的地址
printf("指针数组的指针:\n");
for(i=0;i<3;i++)
printf("%p\n",B[i]);//打印指针数组的地址
return 0;
}
编译结果:
从运行结果中我们可以看到,同样是未初始化,二维数组的地址为连续地址,而指针数组的地址为非连续的无规律地址,说明为仍然处在野指针状态。
三、常见错误
我们在处理多个字符串时,可以用一个char[][]类型的二维数组来存储,也可以使用char*[]的一维指针数组来存储,但使用指针数组时必须先初始化,否则不能直接赋值。
1)错误示例
#include<stdio.h>
#include<string.h>
int main()
{
char A[3][5];//定义二维数组,未初始化
char *B[3];//定义指针数组,未初始化
int i=0;
for(i=0;i<3;i++)
{
scanf("%s",B[i]);//错误!!!不能给未初始化的指针赋值
}
return 0;
}
运行结果:
从运行结果看,典型的非法访问内存导致程序崩溃!!!
2)SO!我们对指针数组初始化一下就OK了吗?
我们可以修改代码如下:
#include<stdio.h>
#include<string.h>
int main()
{
char A[3][10];//定义二维数组,未初始化
char *B[3]={"fantastic","excellent","unbelievable"};//定义指针数组,进行初始化
int i=0;
for(i=0;i<3;i++)
{
printf("%s\n",B[i]);//可以直接给二维数组赋值
}
printf("指针数组的地址:\n");
for(i=0;i<3;i++)
{
printf("%p\n",B[i]);//可以直接给二维数组赋值
}
//输入
for(i=0;i<3;i++)
{
scanf("%s",B[i]);//可以直接给二维数组赋值
}
//打印验证
printf("------------------\n");
for(i=0;i<3;i++)
{
printf("%s\n",B[i]);//可以直接给二维数组赋值
}
return 0;
}
运行结果:
很不幸!从结果来看,显然是失败的。why?从运行结果看,此时的指针数组已经具有明确的地址,所以问题不是野指针的问题了。这里其实是由于使用使用字符串对指针数组初始化时,此时字符串保存在常量区,也就是说指针指向的是一个常量区,是不允许修改其值的!但我们可以改变指针指向,使其指向一个变量区,那么我们就可以对其赋值了,代码如下:
#include<stdio.h>
#include<string.h>
void showIP(char A[][10],int n);
int main()
{
char A[3][10];//定义二维数组,未初始化
char *B[3]={"fantastic","excellent","unbelievable"};//定义指针数组,进行初始化
int i=0;
printf("A[][]的地址:\n");
for(i=0;i<3;i++)
{
printf("%p\n",A[i]);//可以直接给二维数组赋值
}
//将指针数组指针指向A[][]
for(i=0;i<3;i++)
{
B[i]=A[i];//使得指针数组指向一个变量区
}
printf("指针数组的地址:\n");
for(i=0;i<3;i++)
{
printf("%p\n",B[i]);//可以直接给二维数组赋值
}
//输入
for(i=0;i<3;i++)
{
scanf("%s",B[i]);//可以直接给二维数组赋值
}
//打印验证
printf("------------------\n");
for(i=0;i<3;i++)
{
printf("%s\n",B[i]);//可以直接给二维数组赋值
}
return 0;
}
运行结果:
完美,这次大功告成!
四、结论
从上面的探索过程,我们可以得出以下几个结论:
1)指针数组在定义时,不会自己分配有效地址
2)使用字符串(常量)进行初始化时,会使指针指向一个常量区,之后不能对指针指向的地址进行写操作。
3)如果需要对字符串变量输入赋值或者修改时,不建议使用指针数组,直接使用char[][]二维数组,示例如下:
#include<stdio.h>
#include<string.h>
int main()
{
char A[3][10];//定义二维数组,未初始化
char *B[3];//定义指针数组,未初始化
int i=0;
//输入
for(i=0;i<3;i++)
{
scanf("%s",A[i]);//可以直接给二维数组赋值
}
//打印验证
printf("------------------\n");
for(i=0;i<3;i++)
{
printf("%s\n",A[i]);//可以直接给二维数组赋值
}
return 0;
}
运行结果: