指针和数组的定义与声明

导语

在这里我们做种强调的是在两个文件中,定义为数组声明为指针和定义为指声明为数组的这辆中情况。那么我们就需要两个源文件test.c和main.c。

定义为数组,声明为指针

test.c

char arr[] = "abcdef";

main.c

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>

extern char *arr;   //声明

int main()
{
    printf("%s\n", arr);  
    system("pause");
    return 0;
}

就会出现以下的错误:
这里写图片描述
就会出现,读取位置发生访问冲突

  • 首先我们需要知道的是定义和声明使用的是同一块空间,我们在test.c中定义为数组,在main.c中使用,不管声明为数组还是指针都是用的是这一块空间。
    这里将声明的arr当为指针取出来的是四个字节的值,然后在打印字符串时,就会将这四个字节的值作为一个地址去寻找,我们可以先来看看代码呈现。
    这里写图片描述
    我们会发现“64636261”不是dcba的ASSCII码吗?所以我们就知道了它为何地址访问出错。看下图:
    这里写图片描述
    这里指针去访问了四个字节的空间,然后取出了dcba,将dcba当做地址码去取出字符,造成地址访问出错。
    那我们如何在定义为数组、声明为指针的情况下,取出数组中所存的字符串?

  • 要取出字符串,就必须知道首元素’a’的地址,上述的描述,不就让我们知道了arr中存放的就是64636261相当于dcba,我们对arr取地址就相当于取到了abcd的地址,我们在对这个地址强制转换为char*类型,不就取到了一个字节’a’的地址。字符串知道了首元素地址,打印就很方便啦!
    main.c

#include <stdio.h>

extern char *arr;

int main()
{
    //printf("%s\n", arr);
    printf("%s\n", (char*)&arr);
    system("pause");
    return 0;
}

这里写图片描述


定义为指针,声明为数组

test.c

char *p = "abcdef";

main.c

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdlib.h>
#include <stdio.h>

extern char arr[];  //这里只是说他是一个数组,不需要填写数组个数

int main()
{
    printf("%s\n", p);
    system("pause");
    return 0;
}

运行之后就会发现,呀!我的程序运行出来是随机值,不对呀,我明明将它存放进去了。

  • 首先我们就得清楚这个数组里面存放的是什么?
  • 定义为指针,然后指向了字符串”abcdef”,这里指针里面就存的是字符串首元素的地址
  • 声明为数组,定义为指针,大小只有四个字节,所以数组的大小也只有四个字节
  • 指针中存放的是字符串首元素的地址,数组中存放的是字符串首元素的地址,所以打印出来就是乱码了。
  • 图解如下图所示:
    这里写图片描述

那我们如何在定义为指针、声明为数组的情况下,取出指针中所指向的字符串?

  • 我们要找到字符串,就要将指针所存放的四个字节一次取出来,因为字符数组一次只能读一个字节,所以,我们需要把它强转为int*
  • 取出后,我们需要知道它里面的内容,就必须把它解引用,取出四个字节的地址,(int )p
  • 最后,我们要找到’a’的地址,就必须强转为char*,才能取出’a’的地址。
    main.c
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdlib.h>
#include <stdio.h>

extern char p[];    //这里只是说他是一个数组,不需要填写数组个数

int main()
{
    printf("%s\n", (char*)*(int*)p);
    system("pause");
    return 0;
}

这里写图片描述
总结:
1. 定义和声明使用的是同一块空间
2. 指针大小是4个字节,数组大小不一定
3. 指针和数组不一样

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值