【问题标题】:variable redefinition, embedded c变量重新定义,嵌入式 c
【发布时间】:2011-09-16 18:06:15
【问题描述】:

我正在开发一个嵌入式 c 项目,但遇到了全局变量重新定义的问题。

我已将函数声明和定义拆分为几个 .h 和 .c 文件。其中许多函数需要访问 global_vars.h 中定义的全局变量。因此,在头文件的开头,#ifndef,#define 部分,“global_vars.h”。如果我不这样做,您可能会想像我得到一堆未定义的变量错误。

但是,即使 global_vars.h 具有 #ifndef _GLOBAL_VARS_H_ #define...#endif,我也会收到所有全局变量的重新定义错误。我的猜测是,当链接器尝试链接各种目标文件时,由于所有“blah_blah.h”文件中的#include“global_vars.h”,它会看到重新定义。不过,我的理解是,#ifndef... 会处理这个问题。

有什么我忽略的吗?

提前致谢

【问题讨论】:

  • 需要在header中声明变量,并且只在一个源文件中定义。
  • 您的global_vars.h 文件应该将所有变量声明为extern,然后在单独的模块中实际定义它们。我猜你不会这样做?
  • 你是对的。我试试这个,谢谢
  • 作为旁注,如果您的项目中有一个“全局”文件,并且在文件范围内声明了非常量全局变量,则通常表明整个程序设计存在根本性错误。

标签: c header embedded redefinition


【解决方案1】:

链接器永远不会在 global_vars.h 文件中看到任何内容,除非——坏消息! -- 一些全局变量实际上是在该文件中定义。 global_vars.h 应该只包含这些全局变量的声明,从不(嗯,几乎从不)它们的定义。

在 global_vars.h 中,您应该有如下声明:

extern int some_global;

你不能拥有:

int some_global;

如果您在 global_vars.h 中有定义,那么,是的,它们将在链接时被多次定义,因为 #includes global_vars.h 的每个 .c 文件都会对每个定义的变量都有自己的定义。

extern 全局变量的所有定义肯定都在 some .c 文件中。通常哪个 .c 文件并不重要。通常所有的全局变量定义都在一个名为(惊喜!)global_vars.c 的文件中。

所以请确保 global_vars.h 中没有任何全局变量定义,这样你的状态就会很好。

【讨论】:

    【解决方案2】:

    在 H 文件中定义全局变量不是一个好主意。如果您在 C 或 C++ 文件中执行此操作,并且在其他模块中包含和 H 文件,并且这些全局变量作为外部变量,则效果会更好。 像这样>>>

    我的模块c文件

    unsigned short int AGLOBAL = 10; // definer and initializer
    
    void MyFunc(void)
    {
      AGLOBAL+=1; // no need to include anything here cause is defined above
      // more .....
    
    }
    

    我的 H 文件 globals.h

    // this is to include only once
    #ifndef MYH
    #define MYH
    extern unsigned short int AGLOBAL; // no value in here!
    
    #endif
    

    其他模块c文件

    #include globals.h
    
    char SomeOtherFunc(void)
    {
      AGLOBAL+=10; // ok cause its defined by globals.h
      // do more....
    }
    

    【讨论】:

      【解决方案3】:

      首先让我说 extern 关键字适用于 C 变量(数据对象)和 C 函数。基本上 extern 关键字扩展了 C 变量和 C 函数的可见性。可能这就是它被命名为 extern 的原因。

      在 C 函数中使用 extern。默认情况下,C 函数的声明和定义前有 “extern”。这意味着即使我们在 C 函数的声明/定义中不使用 extern,它仍然存在。 比如我们写的时候。

      int foo(int arg1, char arg2);
      

      开头有一个extern,它是隐藏的,编译器如下处理。

      extern int foo(int arg1, char arg2);
      

      C 函数的定义也是如此(C 函数的定义意味着编写函数体)。因此,每当我们定义一个 C 函数时,函数定义的开头都会出现一个 extern。由于声明可以进行多次,而定义只能进行一次,我们可以注意到函数的声明可以在多个 C/H 文件中添加,也可以在单个 C/H 文件中添加多次。但是我们只注意到函数的实际定义一次(即仅在一个文件中)。并且由于 extern 将可见性扩展到整个程序,只要函数的声明是已知的,就可以在整个程序的任何文件中的任何位置使用(调用)函数。 (通过知道函数的声明,C 编译器知道函数的定义存在并继续编译程序)。 以上就是带有 C 函数的 extern 的全部内容。

      1. 声明可以进行任意次数,但只能定义一次。

      2. “extern”关键字用于扩展变量/函数()的可见性。

      3. 默认情况下,函数在整个程序中都是可见的。在函数声明/定义中不需要使用 extern。它的使用是多余的。

      4. 当 extern 与变量一起使用时,它只是声明为未定义。

      5. 作为一个例外,当一个外部变量在初始化时声明时,它也被视为变量的定义。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-07-30
        • 2011-05-29
        • 1970-01-01
        • 2017-04-15
        • 2019-05-27
        • 1970-01-01
        • 1970-01-01
        • 2020-04-04
        相关资源
        最近更新 更多