c - 如何让 GCC 在编译时评估函数?

标签 c gcc pre-compilation

我正在考虑以下问题:我想用一个使用某种查找表的程序对微 Controller (假设是 AVR mega 型)进行编程。

第一次尝试是在单独的文件中找到表并使用任何其他脚本语言/程序/...创建它。在这种情况下,为 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?

最佳答案

这里的一般问题是 sin 调用使这个初始化实际上是非法的,根据 C 语言的规则,因为它本身不是 常量表达式 而你是初始化静态存储持续时间数组,这需要。这也解释了为什么您的数组不在 .data 部分中。

C11 (N1570) §6.6/2,3 常量表达式(强调我的)

A constant expression can be evaluated during translation rather than runtime, and accordingly may be used in any place that a constant may be.

Constant expressions shall not contain assignment, increment, decrement, function-call, or comma operators, except when they are contained within a subexpression that is not evaluated.115)

然而,正如@ShafikYaghmour 的评论所述,GCC 将用其内置的对应函数替换 sin 函数调用(除非存在 -fno-builtin 选项),这很可能被视为常量表达式。根据6.57 Other Built-in Functions Provided by GCC :

GCC includes built-in versions of many of the functions in the standard C library. The versions prefixed with __builtin_ are always treated as having the same meaning as the C library function even if you specify the -fno-builtin option.

关于c - 如何让 GCC 在编译时评估函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42022207/

相关文章:

C 宏产生意外行为

c - 将列表指针发送到函数

c - 如何仅使用一个函数 showCnt() 来显示结构体数组的成员?如何传递参数?

linux - 如何在 Linux 上将 -fPIC 传递给 GCC

ember.js - Ember JS : Could not find property 'action'

c# - 为什么这两个字符串比较会返回不同的结果?

无法在 OpenBSD 上使用 editline 进行编译

c - wchar_t 读取

c - 当在同一文件中定义其调用函数时如何在 C 中模拟函数?

Clang 用户文档