如何在一行源代码中包含几行 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 位变量。