虽然我在一般范围内欢迎这方面的答案,但我主要是要求avr-gcc使其不太广泛。
我已经查看了一些问题,尤其是this和this。他们主要关注语义差异,例如:不能使用static const
代替常量表达式。然而,尽管一般都在谈论内存分配,但他们并没有谈论优化。
让我们看一个例子:
typedef struct {
GPIO_TypeDef *port;
uint8_t pin;
} gpio_pin_t;
static inline void gpio_pin_set(gpio_pin_t gpio, bool set) {
if(set) GPIO_SetBits (gpio.port, 1 << gpio.pin);
else GPIO_ResetBits(gpio.port, 1 << gpio.pin);
}
//elsewhere including above definitions
static const gpio_pin_t gpio_pin = {GPIOE, 8};
void some_function(bool enable) {
gpio_pin_set(gpio_pin, enable);
}
正如你所看到的,我使用结构,所以第三种既定方式(枚举)不是一个选项
我可以期待gcc优化内联函数中的gpio.port
和gpio.pin
访问吗?如果没有,为什么会这样,并且gcc在看到consts时会应用其他优化吗?
完全的一般性,使用static const
变量代替定义,,尤其是超越简单的整数常量,我会失去什么优化?
答案 0 :(得分:3)
这取决于编译器的实现。
如果您从未接受它的地址且未导出符号(对于C,默认情况下,因此您必须使用static
),然后优化程序应启动并优化它。对于简单类型(int
,float
),您可以合理地期望它可以全面工作,但对于struct
- 更好地检查编译器的作用。对于像我的GCC这样的简单结构优化它,消除结构并直接传递它的值,将常量加载到CPU寄存器。对于较大的结构,它可能决定它是不值得的。
您可以生成要检查的代码的汇编列表:
avr-gcc -O<opt> -S somefile.c
或
gcc -O<opt> -S somefile.c
不要忘记优化级别!
使用#define
很糟糕,因为预处理器非常愚蠢 - 它只是在编译之前逐字替换代码。使用const
购买可以更好地输入安全性。考虑这个例子:
#define BYTE_VALUE 257
static const uint8_t sc_value = 257; // at least will show warning
int my_byte = BYTE_VALUE; // no warning, but obviously it's a bug!
答案 1 :(得分:2)
关于抽象:
为什么你在大量的抽象层中淹没了这么简单的东西?您可以放心地假设每个C程序员都知道
的含义PORT |= (1<<pin);
PORT &= ~(1<<pin);
就C程序员而言,这和代码一样可读。通过将此代码隐藏在抽象层中,可以使代码对C程序员的可读性降低,尽管非程序员可能会更容易阅读。但是你希望前者阅读你的代码,而不是后者。
就效率而言,上述也是最快的。编译器很可能会将这些代码直接转换为单个位设置/位清除汇编程序指令。
所以我的建议是抛弃所有的抽象。您不希望将硬件隐藏在嵌入式C程序员之外。您需要隐藏的是特定的硬件实现,因此他们无需为每个新项目重新发明轮子。
一种这样的抽象是在编写与硬件无关的API层时。例如void led_set (bool lit);
。此功能将点亮电路板上的LED。您将它放在抽象文件led.h
中,该文件没有相应的.c文件。因为.c文件仅针对您的特定项目实现:在my_led.c
中,您将拥有实际实现,直接访问GPIO寄存器,设置数据方向和数据。拉电阻调节器,处理信号极性等。
关于您的具体问题:
无法保证GCC会像您期望的那样内联该函数:inline关键字已经过时了,因为现在编译器在决定何时内联函数时比程序员更聪明。我会说很有可能,因为你在编译时启用了最大优化。找出答案的唯一方法就是尝试。
但是,编译器是否内联此函数并不是最重要的。您可能不会有这样极端的实时要求,函数调用开销会影响您的程序。我们在这里谈论几十纳秒:即使是电路板上的数字电子集成电路也不会对这些额外的CPU滴答作出足够快的响应以产生影响。
我每天都在使用基于MCU的实时嵌入式系统,甚至在这些系统中,你很少遇到像这样的极端代码优化很重要的情况。如果你这样做,你将使用DSP,而不是常规MCU,绝对不是AVR。
更重要的是,你的static const
将常量的范围缩小到本地文件,因此没有其他人需要关注它,也不会使全局命名空间混乱。这是一个很好的编程实践,良好的编程实践在10次中有9次胜过手动代码优化。