【发布时间】:2014-03-02 16:46:48
【问题描述】:
序言
我正在使用 avr-g++ 对 AVR 微控制器进行编程,因此我总是需要获得非常高效的代码。
如果函数的参数是编译时常量,GCC 通常可以优化函数,例如我有函数pin_write(uint8_t pin, bool val) 确定AVR 的pin 寄存器(使用我从整数pin 到一对端口/引脚的特殊映射)并写入这些寄存器对应的值。由于它的通用性,这个函数并不算太小。但是如果我用编译时常量pin 和val 调用这个函数,GCC 可以在编译时进行所有计算并消除对几个 AVR 指令的调用,例如
sbi PORTB,1
sbi DDRB,1
安布尔
让我们编写这样的代码:
class A {
int x;
public:
A(int x_): x(x_) {}
void foo() { pin_write(x, 1); }
};
A a(8);
int main() {
a.foo();
}
我们只有一个 A 类对象,它被初始化为一个常量 (8)。因此,可以在编译时进行所有计算:
foo() -> pin_write(x,1) -> pin_write(8,1) -> a couple of asm instructions
但 GCC 不这样做。
令人惊讶的是,但如果我删除全局 A a(8) 并只写
A(8).foo()
我得到了我想要的:
00000022 <main>:
22: c0 9a sbi 0x18, 0 ; 24
24: b8 9a sbi 0x17, 0 ; 23
问题
那么,有没有办法强制 GCC 在编译时对具有常量初始化器的单个全局对象进行所有可能的计算?
由于这个麻烦,我不得不手动扩展这种情况并用这个替换我的原始代码:
const int x = 8;
class A {
public:
A() {}
void foo() { pin_write(x, 1); }
}
UPD. 非常棒:A(8).foo() 内 main 优化为 2 个 asm 指令。 A a(8); a.foo() 也是!但是如果我将A a(8) 声明为全局——编译器会生成大的通用代码。我尝试添加static - 它没有帮助。为什么?
【问题讨论】:
-
如果您将
x声明为const,会发生什么? -
你可以使用模板吗?或者至少是常量表达式?
-
使构造函数
constexpr? -
@StefanoSanfilippo:没有帮助
-
@KerrekSB:我不擅长模板。你能说明你的意思吗?