【问题标题】:In C language, What is the difference between extern buffer[] and extern *buffer?在 C 语言中,extern buffer[] 和 extern *buffer 有什么区别?
【发布时间】:2015-06-18 17:48:14
【问题描述】:

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

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. 有人请解释一下这两种类型有什么区别?

【问题讨论】:

  • 这必须是重复的
  • 我一直交替使用它们。获取不同的地址对我来说毫无意义。
  • 好的,指针和数组不一样。你试图告诉编译器在它是一个数组时寻找一个指针
  • 简而言之:解引用指针比访问数组间接。由于额外的间接性,使用指针声明的代码(当标识符是数组时)会爆炸。在 Peter van der Linden 的 “专家 C 编程 - 深度 C 的秘密” 中有一个非常清楚的解释。

标签: c arrays pointers


【解决方案1】:
extern signed char buffer[];

是一块有地址的内存。

extern signed char *buffer;

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

【讨论】:

    【解决方案2】:

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

    signed char buffer[100];
    

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

    extern signed char *buffer;
    

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

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

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

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

    【讨论】:

      【解决方案3】:

      【讨论】:

      • 这解决了我的问题!非常感谢史蒂夫。+1 的链接。
      【解决方案4】:

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

      尽管signed char *buffer 和signed char buffer[] 的含义相同,但extern 不是其中之一。使用extern 要求编译器将外部定义的解析推迟到链接器。链接器必须非常注意指针和数组的区别,因为两者在内存中的结构不同,不能互换。

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

      【讨论】:

        【解决方案5】:

        两者的区别

        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 在第二种情况下工作,您必须知道数组的大小。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-05-10
          • 1970-01-01
          • 2017-12-26
          • 2019-12-22
          • 1970-01-01
          • 2015-03-18
          • 2023-03-22
          • 2012-11-03
          相关资源
          最近更新 更多