写代码的篮球球痴 嵌入式Linux 2020-03-09
导语在这里我们做种强调的是在两个文件中,定义为数组声明为指针和定义为指声明为数组的这辆中情况。那么我们就需要两个源文件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;
}
总结:- 定义和声明使用的是同一块空间
- 指针大小是4个字节,数组大小不一定
- 指针和数组不一样
转自:https://blog.csdn.net/meng_lemon/article/details/80642938