当由gcc编译然后运行时,代码
int *p; int main() {*p = 1;}
导致分段错误 .
显然,p中包含的内存位置无法写入 .
为什么????
另一方面,
int q[]; int main() {*q = 1;}
运行得很好 .
这里发生了什么??
为什么p只包含只读内存?
第一个示例有一个wild(未显式初始化)指针 . 由于它不是自动变量,因此设置为0,这显然不是您拥有的内存 . 您可以通过以下方式打印出来看到:
printf("%p\n", p)
至于第二个,C99§6.9.2实际上以此为例:
例2如果在包含int i []的翻译单元的末尾;数组我仍然有不完整的类型,隐式初始化器使它有一个元素,在程序启动时设置为零 .
通常,具有暂定定义的对象(无初始化程序)初始化为0,对于数组,这意味着具有元素值0的1元素数组 .
您的第一个示例导致分段错误,因为您正在取消引用NULL . 您永远不会使用值初始化 p ,因为它是全局的,它将为NULL . 因此,你取消引用NULL,并繁荣 .
p
我不确定第二个例子是如何有效的 - gcc注意到它假设 q 是一个1元素的数组,这就是为什么它不会爆炸 .
q
*p = 1; 导致分段错误,因为在分配之前未分配任何内存 .
*p = 1;
*q = 1; 有效,因为编译器(Mac OS X上的gcc 4.2.1)警告q []假定有一个元素 .
*q = 1;
3 回答
第一个示例有一个wild(未显式初始化)指针 . 由于它不是自动变量,因此设置为0,这显然不是您拥有的内存 . 您可以通过以下方式打印出来看到:
至于第二个,C99§6.9.2实际上以此为例:
通常,具有暂定定义的对象(无初始化程序)初始化为0,对于数组,这意味着具有元素值0的1元素数组 .
您的第一个示例导致分段错误,因为您正在取消引用NULL . 您永远不会使用值初始化
p
,因为它是全局的,它将为NULL . 因此,你取消引用NULL,并繁荣 .我不确定第二个例子是如何有效的 - gcc注意到它假设
q
是一个1元素的数组,这就是为什么它不会爆炸 .*p = 1;
导致分段错误,因为在分配之前未分配任何内存 .*q = 1;
有效,因为编译器(Mac OS X上的gcc 4.2.1)警告q []假定有一个元素 .