如何在编译时使GCC评估函数? [英] How to make GCC evaluate functions at compile time?

查看:183
本文介绍了如何在编译时使GCC评估函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在考虑以下问题:我想用一个查找表来编程一个微控制器(假设是一个AVR兆类型)。



第一次尝试是将表定位在单独的文件中,并使用任何其他脚本语言/程序/ ...创建它。在这种情况下,为C创建必要的源文件需要相当多的努力。



我现在的想法是使用预处理器和编译器来处理事情。我试图用一个正弦值表来实现这一点(就像一个例子):

  #include  #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 根据C语言的规则,事实上是非法的,因为它本身不是常量表达式本身,而且你正在初始化静态存储持续时间的数组,这就需要这样做。这也解释了为什么你的数组不在 .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 the sin 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 #included?

解决方案

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆