指针数组和字符类型的二维数组在处理字符串时的区别

版权声明:本文为博主原创文章,未经博主允许不得转载。 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;
}
运行结果:



猜你喜欢

转载自blog.csdn.net/jeffscott/article/details/79090705
今日推荐