最多强制一次包含在嵌入式 C 中
Forcing at most once inclusion in embedded C
我正在开发一个用 ANSI C 编写的嵌入式系统。就其价值而言,它是一个 Pic32MX/MZ(我们在两者上都有系统),尽管它不应该是相关的。我也不会使用 C++ 或 Rust。
我已经编写了控制外设的代码。我只想允许 1 个其他文件引用此外围设备。
所以想象一下我有:
perihperal1.h
peripheral1.c
my_file1.c
myfile2.c
有什么方法可以确保 my_file1.c
或 myfile2.c
中只有 1 个可以有 #include perihperal1.h
?
我找不到在代码中强制执行它的方法,我宁愿强制执行它,而不是仅仅依靠良好的纪律。
编辑:
这样做的目的是我可以将硬件初始化代码与可能与所述外围设备交互的业务逻辑分开。
我想避免设置 UART,将其包含在某处,然后又将其包含在其他地方。它可以通过适当的纪律来完成,但在大型团队中经常会发生错误。
如果有任何正当理由这样做,您可以这样做:
a.h:
int unique_include_a = 1;
a.c:
#include "a.h"
int a()
{
return 123;
}
int main()
{
a();
return 0;
}
b.c:
#include "a.h"
int b()
{
return 456;
}
编译并link:
gcc a.c b.c
linker 应该发出一个错误:
/usr/bin/ld: /tmp/ccmC6JPZ.o:(.data+0x0): multiple definition of `unique_include_a'; /tmp/ccjvwQrZ.o:(.data+0x0): first defined here
collect2: error: ld returned 1 exit status
正确的解决方案是记录 UART 代码。按照“注意:这是单例实现。它只能从项目中的单个代码模块调用。”
也可以包括 运行-time guards 以防止此类尝试。假设您有 uart_init
必须先执行才能使用驱动程序。然后您可以将其实现为:
uart_result_t uart_init (/* params */)
{
static bool initialized=false;
if(initialized)
{
return UART_ERR_MULTIPLE_CALLS; // some error code
}
initialized=true;
...
}
这至少会增加 运行 时间开销,并且尝试进行多次调用会在开发过程中及早发现。
也就是说,除非您希望代码在同一个 MCU 上处理多个相同的 UART 外设,否则您需要以不同的方式实现它。例如,作为一个不透明类型,将指定的 UART 外围设备标记为已采用,并且 returns 一个错误,如上例所示。
我正在开发一个用 ANSI C 编写的嵌入式系统。就其价值而言,它是一个 Pic32MX/MZ(我们在两者上都有系统),尽管它不应该是相关的。我也不会使用 C++ 或 Rust。
我已经编写了控制外设的代码。我只想允许 1 个其他文件引用此外围设备。
所以想象一下我有:
perihperal1.h
peripheral1.c
my_file1.c
myfile2.c
有什么方法可以确保 my_file1.c
或 myfile2.c
中只有 1 个可以有 #include perihperal1.h
?
我找不到在代码中强制执行它的方法,我宁愿强制执行它,而不是仅仅依靠良好的纪律。
编辑:
这样做的目的是我可以将硬件初始化代码与可能与所述外围设备交互的业务逻辑分开。
我想避免设置 UART,将其包含在某处,然后又将其包含在其他地方。它可以通过适当的纪律来完成,但在大型团队中经常会发生错误。
如果有任何正当理由这样做,您可以这样做:
a.h:
int unique_include_a = 1;
a.c:
#include "a.h"
int a()
{
return 123;
}
int main()
{
a();
return 0;
}
b.c:
#include "a.h"
int b()
{
return 456;
}
编译并link:
gcc a.c b.c
linker 应该发出一个错误:
/usr/bin/ld: /tmp/ccmC6JPZ.o:(.data+0x0): multiple definition of `unique_include_a'; /tmp/ccjvwQrZ.o:(.data+0x0): first defined here
collect2: error: ld returned 1 exit status
正确的解决方案是记录 UART 代码。按照“注意:这是单例实现。它只能从项目中的单个代码模块调用。”
也可以包括 运行-time guards 以防止此类尝试。假设您有 uart_init
必须先执行才能使用驱动程序。然后您可以将其实现为:
uart_result_t uart_init (/* params */)
{
static bool initialized=false;
if(initialized)
{
return UART_ERR_MULTIPLE_CALLS; // some error code
}
initialized=true;
...
}
这至少会增加 运行 时间开销,并且尝试进行多次调用会在开发过程中及早发现。
也就是说,除非您希望代码在同一个 MCU 上处理多个相同的 UART 外设,否则您需要以不同的方式实现它。例如,作为一个不透明类型,将指定的 UART 外围设备标记为已采用,并且 returns 一个错误,如上例所示。