这个使用extern关键字的C程序有什么问题?

Vic*_*r S 5 c

我想在main.c中使用来自foo.c的变量a,我写道:

foo.c
#include <stdio.h>

int a[] = {3, 2};

void foo()
{
    printf("foo\taddress of a:%x\n", a);
    printf("foo\tvalue of a[0]:%x\n", a[0]);
}

main.c
#include <stdio.h>

extern int *a;

int main(void)
{
    foo();
    printf("main\taddress of a : %x\n", a);
    printf("main\tvalue of a[0] : %x\n", a[0]);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

和结果输出:

foo address of a:804a014
foo value of a[0]:3
main    address of a : 3
Segmentation fault (core dumped)
Run Code Online (Sandbox Code Playgroud)

为什么?

ken*_*ytm 8

类型aint[2],而不是int*.再试一次

extern int a[2];
Run Code Online (Sandbox Code Playgroud)

C编译器无法跨源文件进行类型检查.因此,当你说int* a,编译器将假设你说实话,使用指针语义,并且不会发出任何编译器错误.

数组和指针之间存在细微差别.我们假设一个32位系统.然后"a"的内容将像这样分发:

    a
0x100       0x104      0x108   ? address
    +-----------+----------+
    |         3 |        2 |   ? content
    +-----------+----------+

什么时候a数组,

  • 表达式的值a将转换为地址a.因此,当您打印时a,您将获得其地址,即"0x100".
  • a[n]C中的操作相当于*(a + n),即an单位推进地址,然后取消引用它以获取内容.因此,a[0]相当于*0x100将内容返回0x100,即"3".

a是一个指针,

  • "值" a是提供的地址的内容.实际上这是常态,数组类型是一种特殊情况.因此,当您打印时a,您将获得该地址的内容,即"3".
  • 手术a[n]还在*(a + n).因此,a[0]等同于*3导致分段错误,因为地址"3"无效.

  • @NiklasR:没有`int a [2]`不是指针,它是一个数组.`extern int a [];`也可以工作,所以差异不是已知的大小. (4认同)