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

本文深入探讨了指针数组的概念及应用,对比了指针数组与二维数组的区别,并通过实例讲解了如何正确初始化和使用指针数组,避免常见的内存访问错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、概念明确

指针数组,是指一个数组中存放的元素是某种类型的指针,二维数组本质上是两个一维数组的合成。当在定义二维数组时,就已经分配给二维数组空间,但是定义一个指针数组,指针数组里面的指针却不会自动初始化,此时的指针仍然是野指针,这时不能直接对其赋值。

 

二、代码阐释

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;
}

运行结果:

 


 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值