在这里我们主要来分析两种情况:
首先我们来闯将两个源文件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; }这里我们就可以看到数组和指针的不一样,指针无论何时大小都是四个字节,而数组却不一定。
同样的两个源文件 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这样也是可以输出的。