在这里我们主要来分析两种情况:
1.定义为数组声明成指针。
首先我们来闯将两个源文件sum.c和test.c
然后在sum.c中我们写这个代码只定义数组并且给它赋值。
char str[] = "abcdef";
test.c中我们用来声明成指针
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
extern *str;
int main()
{
printf("%s\n", str);
system("pause");
return 0;
}
按照我们的理解,数组名是首元素地址,按理来说我们应该可以正常输出“abcdef”
然而并不然我们来看看结果:
哎呦,程序挂掉了。看来情况并不是像我们所想的那样啊。那程序是怎么挂掉的?
我们来分析分析:
首先我们要知道声明和定义的时候指的是一块空间,我们sum.c中定义数组放在一块空间里,
然后在test.c中不管声明成指针还是数组仍然指的是这一块空间,
我么你在这里把str声明成指针的时候,指针大小是几个字节?4个字节,而指针str又是这块空间,所以我们一定能拿到的是前四个字符abcd,不信?我们来试试
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
extern *str;
int main()
{
printf("%x\n", str);
system("pause");
return 0;
}
会输出什么呢?
输出了64636261也许你还是没有发现什么
但这样哪64 63 62 61 这不就是dcba的十六进制吗?
最开始我们一位存放的是数组首元素地址,用%s输出,现在我们知道str指针中存放的是这么一串东西?你说编辑器能给你找到64636261这个地址的位置吗?
说到这 你说我们就非得给它定义成数组,声明成指针还像把它正确输出出来有什么办法呢?
我们要用%s输出肯定得找到a的地址,我们我们刚知道str中存放的是64 63 62 61相当于dcba,
那我们如果对str取地址不就相当于对这块空间的abcd进行取地址了吗?然后再找到它首元素的地址,将&str强制类型转换为char*类型,我们知道char*指向一个字节,这样就可以找到a的地址不就可以解决问题了吗
int main()
{
printf("%s\n", (char *)&str);
system("pause");
return 0;
}
这里我们就可以看到数组和指针的不一样,指针无论何时大小都是四个字节,而数组却不一定。
2.定义成指针声明成数组。
同样的两个源文件
sum.c中
#define _CRT_SECURE_NO_WARNINGS 1
char *str = "abcdef";
test.c中
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
extern str[];
int main()
{
printf("%s\n", str);
system("pause");
return 0;
}
运行结果:
这里输出的是乱码怎么回事呢?我们再来分析分析
其实主要我们要请除指针和数组中存放的是什么,定义与声明指向的是同一块空间,这里定义的是指针,而我们声明成数组,但数组里其实存放的应该是指针变量str的内容而不是字符串也就是首元素的地址,同时指针只开辟了四个字节,所以这里的数组大小肯定也是四个字节,这时我们能用%s输出来当然会输出乱码,因为数组里本来就存放的地址而不是字符串。
如果我们就非得输出来abcdef该怎么办呢?
首先我们知道了str数组中存放的指针变量str的内容,而str的内容就是字符串abcdef的地址,所以我们只需要把它的内容取出来就行了,我们知道指针大小是四个字节,要取出str[]数组的内容,同时我们知道int变量也是所以我们可以先将str强制类型转换成int 然后在解引用,引用出来存放的四个字节,就是字符串的地址,然后再强制类型转换为char 类型,再用%s输出。这样应该是可以输出的。
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
extern str[];
int main()
{
printf("%s\n",(char *)*(int *)str);
system("pause");
return 0;
}
其还可以用指针数组的形式
声明成*str[];
然后输出的时候直接解引用str这样也是可以输出的。