【发布时间】:2011-09-17 04:04:03
【问题描述】:
文件 1.c
int a[10];
文件 main.c:
extern int *a;
int main()
{
printf("%d\n", a[0]);
return 0;
}
给我一个段错误!怎么了?
【问题讨论】:
标签: c arrays pointers segmentation-fault extern
文件 1.c
int a[10];
文件 main.c:
extern int *a;
int main()
{
printf("%d\n", a[0]);
return 0;
}
给我一个段错误!怎么了?
【问题讨论】:
标签: c arrays pointers segmentation-fault extern
当作为参数传递给函数时,或在赋值运算符右侧转换为 r 值时,数组分解或隐式转换为指针。所以像:
int array[10];
int* a = array; //implicit conversion to pointer to type int
void function(int* a);
function(array); //implicit conversion to pointer to type int
工作得很好。但这并不意味着数组本身就是指针。因此,如果您将数组视为指针,实际上您将数组类型视为保存指向int 对象的地址的指针。由于您的数组实际上是int 对象的序列,而不是指向int 对象的指针,因此您实际上是在尝试取消引用一些未指向任何有效位置的内存位置(即@987654326 中的第一个插槽@ 是一个数字整数值,例如 0,就像取消引用 NULL)。所以这就是为什么你会出现段错误。请注意,如果你做了这样的事情:
int array[] = { 1, 2, 3, 4, 5};
int b = *array;
这仍然有效,因为array 再次被隐式转换为指向包含整数值序列的内存块的指针,然后取消引用以获取第一个序列中的值。但是在您的情况下,通过将当前代码模块的数组声明为外部定义的指针,而不是数组,它将跳过通常完成的对指针的隐式转换,并像使用数组对象一样使用它是指向对象本身的指针,而不是对象数组。
【讨论】:
在C FAQ 中有很好的解释。还有a followup。第二个链接中的图片价值一百万美元。
char a[] = "hello";
char *p = "world";
简答:使用extern int a[]。
【讨论】:
有点晚了,这个问题的副本刚刚输入(并关闭)。这里的答案没有提到头文件...
如果将数组a 的声明放在它所属的头文件中,而不是将其放在.c 文件中,则问题将在编译时被发现。然后应该将头文件包含在两个 .c 文件中,编译器可以看到您声明的内容是错误的。
您的头文件将包含:
extern int myarray[];
如果您将a 声明为指针,则会得到类似“error: conflicting types for a”的信息。
【讨论】:
基本上你需要像这样编写你的 main.c:
extern int a[];
int main()
{
printf("%d\n", a[0]);
return 0;
}
【讨论】:
查看以下代码的输出。
文件1.c
#include <stdio.h>
extern int* my_arr;
void my_print()
{
printf("%d", my_arr);
}
main.c
#include <stdio.h>
int my_arr[2] = {1,2};
extern void my_print();
void main()
{
my_print();
}
输出
1
在 File1.c 中 my_arr 是一个值为 1 的指针变量。这意味着 my_arr[] 的第一个元素已分配给它。然后如果你使用 *my_arr 访问内存位置 ox1,你会得到 seg 错误,因为你不能访问 ox01。
为什么 my_arr 指针被赋值为 1(my_arr[] 的第一个元素)?
与汇编程序的工作方式有关。阅读this article
为什么你的代码不能访问 0x01 ?
我知道这与操作系统不允许用户代码访问某些地址空间有关。这是我知道的全部。如果您想了解更多信息,请在 Google 上搜索。
【讨论】: