C中的外部行为

时间:2013-07-12 12:00:34

标签: c extern

如果我在file1.c中声明int Array[10];

在file2.c中,如果我有这样的函数

extern int *Array;
fun()
{
    Array[0]=10; 
}

这有没有问题?

2 个答案:

答案 0 :(得分:8)

是的,有问题。

您声明Array指针,而是数组。这两个是非常不同的对象,在这里你基本上是向编译器提供虚假信息。

请注意,在两种情况下,访问元素的C语法都是Array[0],但如果Array是指针变量,则所需的机器代码将不同于Array而不是数组(指针有一个额外的间接)。

例如,如果Array1被声明为extern int *Array,则Array1[ix] += 3由gcc生成的机器代码为:

movslq  ix(%rip), %rax        ;; Load index value from location ix
movq    Array1(%rip), %rdx    ;; Load pointer value from location Array1
leaq    (%rdx,%rax,4), %rax   ;; Compute rax as pointer + index*4
addl    $3, (%rax)            ;; Add 3 to the location pointed by rax

如果将Array2声明为extern int Array2[10]Array2[ix] += 3的代码就是:

movslq  ix(%rip), %rax        ;; Load in rax the index value from location ix
addl    $3, Array2(,%rax,4)   ;; Add 3 to the location Array2 + index*4

正如您在第一种情况中所看到的那样,存在额外的间接寻址,并且读取地址Array1处的内存内容以查找应在内存中进行增量的位置。在第二种情况下,只需要读取索引来计算要递增的位置。

为了让C中的东西更加混乱,在很多情况下,数组“衰减”成指向第一个元素的指针,所以例如,如果你有一个函数,期望一个指针传递一个数组是好的,因为编译器会处理处理差异。

必须告诉编译器内存中的对象是数组还是指针,因为语义不同;相反,问题中的代码就是这样......程序的一部分会分配一个数组并告诉程序的某些部分它是一个指针。

答案 1 :(得分:0)

声明extern int *Array未声明数组,因此与实际定义不匹配。你必须声明:

extern int Array[];

C99(ISO / IEC 9899)§6.5.7.2数组声明符

  

注意声明之间的区别

extern int *x;
extern int y[];
  

第一个声明x是一个指向int的指针;第二个声明y是一个未指定大小的int数组(一个不完整的类型),其存储在其他地方定义。