在C语言中,extern buffer []和extern * buffer之间有什么区别?

时间:2015-06-18 17:48:15

标签: c arrays pointers

我在微软文章中阅读了以下信息;

https://support.microsoft.com/en-us/kb/44463

  

下面的文本提供了一个常见编程错误的示例,即混淆数组和指针声明:   考虑将应用程序分为几个模块。在一个模块中,声明一个数组如下:

  signed char buffer[100];
     

在另一个模块中,声明以下变量以访问该数组:

 extern signed char *buffer;           // FAILS  
 extern signed char buffer[];          // WORKS
     

如果您在CodeView调试器中查看代码,则表明*buffer声明产生的地址与buffer[]声明的地址不同。

  1. 但我无法理解为什么我们无法使用*buffer访问该数组 我们可以使用buffer[]访问它。

  2. 请有人解释一下这两种类型有什么区别?

5 个答案:

答案 0 :(得分:3)

extern signed char buffer[];

拥有地址的一块内存。

extern signed char *buffer;

可能或可能不指向一块内存的变量 - 它是包含一个可能有效或无效的地址的变量。

答案 1 :(得分:1)

之间的差异
extern signed char *buffer;
extern signed char buffer[]; 

与您在

时看到的相同
signed char *buffer;
signed char buffer[100];

在一个函数中。

我看到以下差异:

差异1

当你有:

extern signed char *buffer;

你可以使用:

buffer = malloc(10);

当你有:

extern signed char buffer[]; 

你做不到。

差异2

在第一种情况下,buffer可能为NULL。在第二种情况下,它不是。

差异3

&buffer会产生不同的类型。例如,您可以使用:

printf("pointer 1: %p\n", &buffer+1);

在第一种情况下但你不能在第二种情况下使用它。要让&buffer+1在第二种情况下工作,您必须知道数组的大小。

答案 2 :(得分:1)

这个问题更多的是关于C链接器而不是关于C语言。

虽然signed char *buffersigned char buffer[]的含义相同,但extern不是其中之一。使用extern要求编译器将外部定义的解析推迟到链接器。链接器必须非常讲究指针和数组之间的区别,因为它们在内存中具有不同的结构,并且不能互换处理。

请注意,尽管这些声明与链接器不同,但它们并不会改变程序员使用这样的外部数组所做的事情:在这两种情况下,您都无法访问声明的数组的大小(即100),语法访问数组元素保持不变,指针算法保持不变。

答案 3 :(得分:1)

在一个模块中,您定义一个名为signed char的{​​{1}}大小为100的数组。该对象将使用100个字节的内存:

buffer

在另一个模块中,你声明 signed char buffer[100]; 是另一个东西,指向buffer的指针,即4或8字节的内存,可以保存一个地址数组或单个signed char的数组。

char

编译器一次只知道一个模块,因此无法检查此声明是否与实际的定义一致。它与此声明一致地编译代码,发出引用外部符号extern signed char *buffer; 的机器代码,该外部符号将在链接时解析。

在链接时,链接器不知道类型,它只依赖于名称。因此,它从一个模块解析对buffer的引用,并使用另一个模块中的定义的实际地址。

在运行时,您会得到未定义的行为,因为一个模块使用buffer作为buffer的数组,它是,而另一个模块从同一地址加载指针的值,解释字节完全不同。

声明属于标头文件,并且应始终包含在实际定义对象的文件中标题中声明

答案 4 :(得分:1)