如何在一行源代码中包含几行 C 代码 (AVR-GCC)
how to include several lines of C code in one line of source code (AVR-GCC)
有没有办法添加编译器会用多行代码替换的标识符?
我阅读了宏和内联函数,但一无所获。
我需要编写一个中断服务例程并且不调用任何函数来提高速度。
问题是我有几个需要使用函数的情况,所以目前我只是在很多地方重复所有几行。
例如:
void ISR()
{
int a = 1;
int b = 2;
int c = 3;
// do some stuff here ...
int a = 1;
int b = 2;
int c = 3;
// do more stuff here ...
int a = 1;
int b = 2;
int c = 3;
}
功能页面很多,我需要代码更易读。
您可以使用 inline
函数,该函数将被集成到源代码中调用它的地方而不是真正被调用(请注意,此行为取决于编译器支持和优化设置或使用等多种因素-fno-inline
标记功能)。 GCC documentation on inline functions.
为了完整性 - 另一种方法是将 // do some stuff here...
定义为预处理器宏,它再次被插入到调用的地方;这次是预处理器——所以没有类型安全,更难调试和阅读。通常好的经验法则是 不要为可以用函数 完成的事情编写宏。
我基本上同意其他人对为此使用宏的保留意见。但是,为了回答您的问题,可以使用反斜杠创建多行宏。
#define INIT_VARS \
int a = 1; \
int b = 2; \
int c = 3;
#define RESET_VARS \
a = 1; \
b = 2; \
c = 3;
void ISR()
{
INIT_VARS
// do some stuff here ...
RESET_VARS
// do more stuff here ...
RESET_VARS
}
您是对的 - 建议您不要在 ISR 中放置函数调用。并不是说您不能这样做,而是根据调用的类型,它可能会成为内存负担。主要原因是时间问题。 ISR 应该快速进出。你不应该在里面做很多扩展工作。
也就是说,这是您实际使用内联函数的方法。
// In main.c
#include static_defs.h
//...
void ISR() {
inline_func();
// ...
inline_func();
}
// In static_defs.h
static inline void inline_func(void) __attribute__((always_inline));
// ... Further down in file
static inline void inline_func(void) {
// do stuff
}
编译器基本上只是多次将“do stuff”代码粘贴到 ISR 中,但正如我之前所说,如果它是一个复杂的函数,在单个 ISR 中多次执行它可能不是一个好主意, 是否内联。最好设置某种标志并在主循环中执行此操作,以便其他中断也可以完成它们的工作。然后,你可以使用一个普通的函数来节省程序内存space。这取决于您真正在做什么以及 when/why 它需要完成。
如果您实际上设置变量并返回值,那也很好,尽管设置多个变量将通过 passing/returning 结构或使用指向描述所有相关变量的结构的指针来完成。
如果您更喜欢使用宏(我不会,因为 function-like 应该避免使用宏),下面是一个例子:
#define RESET_VARS() do { \
a = 1; \
b = 2; \
c = 3; \
while (0)
//...
void ISR() {
uint8_t a=1, b=2, c=3;
RESET_VARS();
// ...
RESET_VARS();
}
此外,您说这是一个假设,但建议使用 中的 bit-width typedef(当您包含 时自动包含,例如uint8_t 而不是 int。在具有 AVR-GCC 的 8 位 MCU 上,一个 int 是一个 16 位有符号变量,它需要(至少)2 个时钟周期用于每个需要一个时钟周期的操作带有一个 8 位变量。
有没有办法添加编译器会用多行代码替换的标识符?
我阅读了宏和内联函数,但一无所获。
我需要编写一个中断服务例程并且不调用任何函数来提高速度。 问题是我有几个需要使用函数的情况,所以目前我只是在很多地方重复所有几行。
例如:
void ISR()
{
int a = 1;
int b = 2;
int c = 3;
// do some stuff here ...
int a = 1;
int b = 2;
int c = 3;
// do more stuff here ...
int a = 1;
int b = 2;
int c = 3;
}
功能页面很多,我需要代码更易读。
您可以使用 inline
函数,该函数将被集成到源代码中调用它的地方而不是真正被调用(请注意,此行为取决于编译器支持和优化设置或使用等多种因素-fno-inline
标记功能)。 GCC documentation on inline functions.
为了完整性 - 另一种方法是将 // do some stuff here...
定义为预处理器宏,它再次被插入到调用的地方;这次是预处理器——所以没有类型安全,更难调试和阅读。通常好的经验法则是 不要为可以用函数 完成的事情编写宏。
我基本上同意其他人对为此使用宏的保留意见。但是,为了回答您的问题,可以使用反斜杠创建多行宏。
#define INIT_VARS \
int a = 1; \
int b = 2; \
int c = 3;
#define RESET_VARS \
a = 1; \
b = 2; \
c = 3;
void ISR()
{
INIT_VARS
// do some stuff here ...
RESET_VARS
// do more stuff here ...
RESET_VARS
}
您是对的 - 建议您不要在 ISR 中放置函数调用。并不是说您不能这样做,而是根据调用的类型,它可能会成为内存负担。主要原因是时间问题。 ISR 应该快速进出。你不应该在里面做很多扩展工作。
也就是说,这是您实际使用内联函数的方法。
// In main.c
#include static_defs.h
//...
void ISR() {
inline_func();
// ...
inline_func();
}
// In static_defs.h
static inline void inline_func(void) __attribute__((always_inline));
// ... Further down in file
static inline void inline_func(void) {
// do stuff
}
编译器基本上只是多次将“do stuff”代码粘贴到 ISR 中,但正如我之前所说,如果它是一个复杂的函数,在单个 ISR 中多次执行它可能不是一个好主意, 是否内联。最好设置某种标志并在主循环中执行此操作,以便其他中断也可以完成它们的工作。然后,你可以使用一个普通的函数来节省程序内存space。这取决于您真正在做什么以及 when/why 它需要完成。
如果您实际上设置变量并返回值,那也很好,尽管设置多个变量将通过 passing/returning 结构或使用指向描述所有相关变量的结构的指针来完成。
如果您更喜欢使用宏(我不会,因为 function-like 应该避免使用宏),下面是一个例子:
#define RESET_VARS() do { \
a = 1; \
b = 2; \
c = 3; \
while (0)
//...
void ISR() {
uint8_t a=1, b=2, c=3;
RESET_VARS();
// ...
RESET_VARS();
}
此外,您说这是一个假设,但建议使用