【发布时间】:2015-03-21 12:27:15
【问题描述】:
我正在考虑以下问题:我想用一个使用某种查找表的程序对微控制器(比如 AVR 巨型类型)进行编程。
第一次尝试是在单独的文件中找到表并使用任何其他脚本语言/程序/....创建它。在这种情况下,为 C 创建必要的源文件需要付出相当多的努力。
我现在的想法是使用预处理器和编译器来处理事情。我尝试使用正弦值表来实现这一点(仅作为示例):
#include <avr/io.h>
#include <math.h>
#define S1(i,n) ((uint8_t) sin(M_PI*(i)/n*255))
#define S4(i,n) S1(i,n), S1(i+1,n), S1(i+2,n), S1(i+3,n)
uint8_t lut[] = {S4(0,4)};
void main()
{
uint8_t val, i;
for(i=0; i<4; i++)
{
val = lut[i];
}
}
如果我编译此代码,我会收到有关 sin 函数的警告。在程序集中,.data 部分没有任何内容。如果我只是删除第三行中的sin,我会得到程序集中的数据。显然,所有信息在编译时都可用。
您能否告诉我是否有办法实现我的意图:编译器会尽可能多地离线计算值?或者是使用外部脚本/程序/...计算表条目并将它们添加到一个单独的文件中的最佳方法,该文件将只是 #included?
【问题讨论】:
-
“相当努力” - 使用良好的脚本语言?肯定比用 C 解决问题要少......
-
C++11(使用 C++14 改进)有
constexpr作为编译器在编译时执行函数的提示。 -
@johannes:
constexpr没有优势。它只是允许在编译时评估一个表达式(甚至强制编译器对其进行评估,例如通过分配给一个枚举并不能阻止它在运行时在不同位置重新评估相同的源文件!)。它不强制或暗示任何事情。也就是说,我的 GCC 将 OP 中的代码 sn-p 优化为编译时评估的查找表(没有任何特殊的特殊舞蹈)。 -
我commented below 如果您使用
-fno-builtin,关于sin的警告将变为错误,这是因为gcc当前将大多数数学函数视为常量表达式,如果它使用内置版本. -
您的
sin只会返回-1/255,0或1。也许你会使用`((uint8_t) (sin(M_PI*(i)/n)+1)/2*255)`
标签: c gcc pre-compilation