[英]What happens when actual and extern types are different?
我有两个文件:
extern char *s;
int main()
{
puts(s);
}
char s[] = "hello";
我同时编译它们,没有错误。 但是程序在运行时崩溃了。 为什么? C语言规范的哪一部分说这是非法的?
如果你想真正了解它 为什么崩溃(而不是为什么它不应该工作):
数组是内存中的一系列事物。 所以
char s[] = "hello";
这个变量的内存布局看起来像这样(假设它从0x00123400开始,带有4个字节的指针):
0x00123400: 'h' <- address of s
0x00123401: 'e'
0x00123402: 'l'
0x00123403: 'l'
0x00123404: 'o'
0x00123405: '\0'
要获取字符串的地址,它只使用固定的数字0x00123400。
指针保存其他内容的地址。 如果你有:
char *s = "hello";
然后编译器将数组“hello”放在某处,然后用其地址填充s:
0x00123400: 0x00 <- address of s
0x00123401: 0x56
0x00123402: 0x78
0x00123403: 0x9A
0x0056789A: 'h' <- what s points to
0x0056789B: 'e'
0x0056789C: 'l'
0x0056789D: 'l'
0x0056789E: 'o'
0x0056789F: '\0'
要获取字符串的地址,它从固定数字0x00123400开始,并读取该位置的数字。
现在,如果你的变量实际上是一个char[]
并且你告诉编译器它是一个char*
,那么它将把它当作指针。 这意味着它将从变量的地址开始,读取那里的数字,并使用该数字作为字符串的地址。
这个数字是多少? 好吧,我说过:
0x00123400: 'h' <- address of s
0x00123401: 'e'
0x00123402: 'l'
0x00123403: 'l'
但那是谎言 - 我们都知道记忆只存储数字,而不是字母。 它只是简写,所以人们不必记住ASCII表。 真正存储的是:
0x00123400: 0x68 <- address of s
0x00123401: 0x65
0x00123402: 0x6C
0x00123403: 0x6C
因此,您的程序将读取0x68656C6C,然后它将尝试从地址0x68656C6C开始打印字符串,这很可能是无效的地址。
(注意:我在这个答案中忽略了字节顺序)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.