如何在编译时使GCC评估函数? [英] How to make GCC evaluate functions at compile time?
问题描述
我正在考虑以下问题:我想用一个查找表来编程一个微控制器(假设是一个AVR兆类型)。
第一次尝试是将表定位在单独的文件中,并使用任何其他脚本语言/程序/ ...创建它。在这种情况下,为C创建必要的源文件需要相当多的努力。
我现在的想法是使用预处理器和编译器来处理事情。我试图用一个正弦值表来实现这一点(就像一个例子):
#include
根据C语言的规则,事实上是非法的,因为它本身不是常量表达式本身,而且你正在初始化静态存储持续时间的数组,这就需要这样做。这也解释了为什么你的数组不在#include< math.h>
#define S1(i,n)((uint8_t)sin(M_PI *(i)/ n * 255))
#define S4(i,n)S1 ),S1(i + 1,n),S1(i + 2,n),S1(i + 3,n)
uint8_t lut [] = {S4(0,4)};
void main()
{
uint8_t val,i; (i = 0; i <4; i ++)
{
val = lut [i];
$ b如果我编译这段代码,我会收到有关sin
函数。进一步在程序集中,在.data
部分中没有任何内容。如果我只是删除第三行中的sin
,我会得到程序集中的数据。显然,所有的信息都可以在编译时使用。
你能告诉我是否有办法实现我的意图:编译器计算出的离线值可能是多少?或者是使用外部脚本/程序/ ...来计算表项并将其添加到单独的文件中的最好方法,该文件将只是
#include
d?解决方案这里的一般问题是
sin .data
部分。
C11(N1570)§6.6/ 2, 3常量表达式(强调我的)
常量表达式可以在转换过程中被评估,而不是
运行时,因此可用于常量可能为
的任何地方。
常量表达式不得包含赋值,增量,
递减,函数调用或逗号运算符,除非它们是包含在未评估的子表达式中的
.115)
然而,由@ ShafikYaghmour的评论GCC将用它的内置对象替换
sin
函数调用(除非-fno-builtin
选项存在),这可能会被视为常量表达式。根据 6.57 GCC提供的其他内置功能:
GCC包含
标准C库中许多函数的内置版本。前缀为__ builtin _
的版本总是被
视为与C库函数具有相同的含义,即使
指定了
I am thinking about the following problem: I want to program a microcontroller (let's say an AVR mega type) with a program that uses some sort of look-up tables.
The first attempt would be to locate the table in a separate file and create it using any other scripting language/program/.... In this case there is quite some effort in creating the necessary source files for C.
My thought was now to use the preprocessor and compiler to handle things. I tried to implement this with a table of sine values (just as an example):
#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]; } }
If I compile this code I get warnings about the
sin
function. Further in the assembly there is nothing in the section.data
. If I just remove thesin
in the third line I get the data in the assembly. Clearly all information are available at compile time.Can you tell me if there is a way to achieve what I intent: The compiler calculates as many values as offline possible? Or is the best way to go using an external script/program/... to calculate the table entries and add these to a separate file that will just be
#include
d?解决方案The general problem here is that
sin
call makes this initialization de facto illegal, according to rules of C language, as it's not constant expression per se and you're initializing array of static storage duration, which requires that. This also explains why your array is not in.data
section.C11 (N1570) §6.6/2,3 Constant expressions (emphasis mine)
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)
However as by @ShafikYaghmour's comment GCC will replace
sin
function call with its built-in counterpart (unless-fno-builtin
option is present), that is likely to be treated as constant expression. According to 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.
这篇关于如何在编译时使GCC评估函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!