2

我正在尝试定义一组全局变量来配置我的设备,大约 10 个在专用的 .c 文件中,将在编译时定期更改(根据设备要求),我希望这些在这个单独的文件,因此它们都可以轻松更改。然后在我的程序中的各种文件中调用这些变量。并且从不改变只读取。问题是我的编译器(用于 PIC MCU 的 XC8)没有定义变量,因为它只能看到文件中变量的一次使用,即使在整个程序中使用 extern 调用它也是如此。

配置文件

unsigned int Global_A;
unsigned int Global_B;
void config(void);

配置文件

void config(void)
{
   unsigned int Global_A=987;
   unsigned int Global_B=123;
}

prog_a.h

extern unsigned int Global_A;
extern unsigned int Global_B;
unsigned int var_A;
void prog_a(void);

prog_a.c

unsigned int var_A=0;
void prog_a(void);
{
   var_A=Global_A+Global_B;
}

主程序

#include config.h
#include prog_a.h

void main(void)
{
   while(1)
   {
      config();
      prog_a();
   }
}

结果,等效的 var_A 始终为 0,因为编译器已经取消了 config.c,因为它看不到再次调用的变量。

我假设答案对那些更精通的人来说非常明显,但我在网上找不到任何东西。我在使用 extern 和 globals 之前没有遇到任何问题,当它们在定义的文件中使用时。但我可能只是从根本上错误地使用它,所以请随意责备我。

提前致谢。

ps 如果不是很明显,这是一个示例代码来说明我的问题。

4

3 回答 3

4

您的函数配置在函数范围内声明了两个新变量(它们的名称隐藏了全局变量的名称)。它们不存在于它之外的任何地方,并且给它们赋值什么都不做。如果您的目标是初始化全局变量,则需要执行以下操作:

// config.h
extern unsigned int Global_A;
extern unsigned int Global_B;
void config(void);

// config.c
unsigned int Global_A;
unsigned int Global_B;
void config(void) {
   Global_A=987;
   Global_B=123;
}
于 2020-12-01T21:33:41.653 回答
2

使用extern关键字,必须声明一次变量(最好在头文件中)在对声明语句具有可见性的 .c 文件中定义一次。这就对了。在需要extern定义变量的地方,出现声明语句#include的头文件。

另请注意,在全局范围内(即不在函数中)定义 extern变量也很重要。

配置.h:

#include "prog_a.h"
//unsigned int Global_A;
//unsigned int Global_B;
void config(void);

主程序

#include config.h
#include prog_a.h
...
//suggest defining these here:
unsigned int Global_A=0;//define outside of function
unsigned int Global_B=0;
...

配置文件

#include "prog_a.h"
...

void config(void)
{
   Global_A=987;
   Global_B=123;
}
于 2020-12-01T21:23:32.327 回答
0

您的全局变量都是类型int,那么为什么不直接使用#define呢?

将文件更改config.h

#define Global_A 789    
#define Global_B 123

您实际上不必声明任何int变量来保存这些值,此外,它们将是const不可修改的。


这就是我们“过去”所做的方式,但在过去的十年或两年中,我看到越来越多的实际将这些配置值存储在外部文本文件中

它可以是 .INI、XML 或 JSON 等,这取决于您。

您只需创建不同的文件,比如说Singapore.iniand Paris.iniandAuckland.ini等,每个文件都包含一个键/值对。

例如

time_zone = X
population = Y

等等等等

然后,在您的 main 开始时,将文件读入并存储值 - 但不是在全局变量中,这些天不受欢迎。将它们读入 config.c 本地的变量中,并让 config.c/h 提供方法来读取它们的值,例如GetTimeZone()andGetPoulation()

不要担心任何代码大小或运行时间影响,因为任何体面的编译器都会内联这些函数调用。

在外部文本文件中读取“全局”配置值的一个优点是您只需要构建一次软件。您不需要为每个配置重新构建并拥有一个可执行文件,这是您当前正在走的路。

首先,这使得测试您的软件(尤其是自动化测试)变得更加容易,只需编辑文本文件或提供一个新文件。

此外,由于您只有一个可执行文件,因此您可以将其发送给所有用户/客户,并为每个用户/客户提供定制的配置文件。您只需更改配置文件即可完全控制和更改软件的功能。你可能想考虑一下。

于 2020-12-01T21:41:09.003 回答