编译器删除的配置变量
Configurations variables removed by compiler
我正在尝试定义一组全局变量来配置我的设备,大约 10 个在专用的 .c 文件中,将在编译时定期更改(根据设备要求),我想要这些都在这个单独的文件中,因此它们都可以轻松更改。然后在我的程序中的各种文件中调用这些变量。并且永远不会改变只读。问题是我的编译器(PIC MCU 的 XC8)没有定义变量,因为它只能看到文件中变量的一次使用,即使它在整个程序中都是用 extern 调用的。
config.h
unsigned int Global_A;
unsigned int Global_B;
void config(void);
config.c
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;
}
main.c
#include config.h
#include prog_a.h
void main(void)
{
while(1)
{
config();
prog_a();
}
}
因此,等效的 var_A 始终为 0,因为编译器已经取消了 config.c,因为它看不到再次调用的变量。
我假设答案对于那些更精通的人来说是显而易见的,但我在网上找不到任何东西。在定义的文件中使用 extern 和 globals 之前,我在使用 extern 和 globals 时没有遇到任何问题。但我可能只是从根本上错误地使用了它,所以请随时批评我。
提前致谢。
p.s 如果不是很明显,这是一个示例代码来说明我的问题。
使用 extern
关键字需要 声明 变量一次(最好在头文件中) define 一次在对声明语句具有可见性的 .c 文件中。这就对了。 extern
定义的变量是必需的,#include
出现 声明 语句的头文件。
另请注意,在 global 范围内 define extern
变量也很重要(即不在功能)。
config.h:
#include "prog_a.h"
//unsigned int Global_A;
//unsigned int Global_B;
void config(void);
main.c
#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;
...
config.c
#include "prog_a.h"
...
void config(void)
{
Global_A=987;
Global_B=123;
}
您的函数配置在函数范围内声明了两个新变量(它们的名称隐藏了全局变量的名称)。它们不存在于它之外的任何地方,为它们赋值也没有任何作用。如果你的目标是让它初始化全局变量,你需要这样做:
// 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;
}
你的全局变量都是int
类型的,为什么不直接使用#define
呢?
将文件 config.h
更改为
#define Global_A 789
#define Global_B 123
您实际上不必声明任何 int
变量来保存这些值,此外,它们将 const
并且不可修改。
这就是我们“过去”做的方式,但在过去一两年中,我看到越来越多的人将这些配置值实际存储在外部文本文件中
它可以是 .INI,或 XML 或 JSON,等等,由您决定。
您只需创建不同的文件,比方说 Singapore.ini
和 Paris.ini
和 Auckland.ini
,等等,每个包含一对 key/value。
例如
time_zone = X
population = Y
等等,等等
然后,在您的主程序开始时,读取文件并存储值 - 但不是在全局变量中,这些天是 frowned upon。将它们读入 config.c 的局部变量,并使用 config.c/h provode 方法来读取它们的值,例如 GetTimeZone()
和 GetPoulation()
,等等
不必担心任何代码大小或 运行 时间影响,因为任何体面的编译器都会 in-line 这些函数调用。
在外部文本文件中读取“全局”配置值的一个优点是您只需要构建一次软件。您不需要为每个配置重建并拥有一个可执行文件,这是您当前正在走的路。
首先,这使得测试您的软件(尤其是自动化测试)变得更加容易,只需编辑文本文件或提供一个新文件即可。
此外,由于您只有一个可执行文件,您可以将其发送到 users/customers 的 all,并且给每个人一个定制的配置文件。只需更改配置文件,您就可以完全控制和更改软件的功能。您可能需要考虑一下。
我正在尝试定义一组全局变量来配置我的设备,大约 10 个在专用的 .c 文件中,将在编译时定期更改(根据设备要求),我想要这些都在这个单独的文件中,因此它们都可以轻松更改。然后在我的程序中的各种文件中调用这些变量。并且永远不会改变只读。问题是我的编译器(PIC MCU 的 XC8)没有定义变量,因为它只能看到文件中变量的一次使用,即使它在整个程序中都是用 extern 调用的。
config.h
unsigned int Global_A;
unsigned int Global_B;
void config(void);
config.c
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;
}
main.c
#include config.h
#include prog_a.h
void main(void)
{
while(1)
{
config();
prog_a();
}
}
因此,等效的 var_A 始终为 0,因为编译器已经取消了 config.c,因为它看不到再次调用的变量。
我假设答案对于那些更精通的人来说是显而易见的,但我在网上找不到任何东西。在定义的文件中使用 extern 和 globals 之前,我在使用 extern 和 globals 时没有遇到任何问题。但我可能只是从根本上错误地使用了它,所以请随时批评我。
提前致谢。
p.s 如果不是很明显,这是一个示例代码来说明我的问题。
使用 extern
关键字需要 声明 变量一次(最好在头文件中) define 一次在对声明语句具有可见性的 .c 文件中。这就对了。 extern
定义的变量是必需的,#include
出现 声明 语句的头文件。
另请注意,在 global 范围内 define extern
变量也很重要(即不在功能)。
config.h:
#include "prog_a.h"
//unsigned int Global_A;
//unsigned int Global_B;
void config(void);
main.c
#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;
...
config.c
#include "prog_a.h"
...
void config(void)
{
Global_A=987;
Global_B=123;
}
您的函数配置在函数范围内声明了两个新变量(它们的名称隐藏了全局变量的名称)。它们不存在于它之外的任何地方,为它们赋值也没有任何作用。如果你的目标是让它初始化全局变量,你需要这样做:
// 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;
}
你的全局变量都是int
类型的,为什么不直接使用#define
呢?
将文件 config.h
更改为
#define Global_A 789
#define Global_B 123
您实际上不必声明任何 int
变量来保存这些值,此外,它们将 const
并且不可修改。
这就是我们“过去”做的方式,但在过去一两年中,我看到越来越多的人将这些配置值实际存储在外部文本文件中
它可以是 .INI,或 XML 或 JSON,等等,由您决定。
您只需创建不同的文件,比方说 Singapore.ini
和 Paris.ini
和 Auckland.ini
,等等,每个包含一对 key/value。
例如
time_zone = X
population = Y
等等,等等
然后,在您的主程序开始时,读取文件并存储值 - 但不是在全局变量中,这些天是 frowned upon。将它们读入 config.c 的局部变量,并使用 config.c/h provode 方法来读取它们的值,例如 GetTimeZone()
和 GetPoulation()
,等等
不必担心任何代码大小或 运行 时间影响,因为任何体面的编译器都会 in-line 这些函数调用。
在外部文本文件中读取“全局”配置值的一个优点是您只需要构建一次软件。您不需要为每个配置重建并拥有一个可执行文件,这是您当前正在走的路。
首先,这使得测试您的软件(尤其是自动化测试)变得更加容易,只需编辑文本文件或提供一个新文件即可。
此外,由于您只有一个可执行文件,您可以将其发送到 users/customers 的 all,并且给每个人一个定制的配置文件。只需更改配置文件,您就可以完全控制和更改软件的功能。您可能需要考虑一下。