C预处理器可以执行算术吗?如果是,如何执行算术?

我正在为微控制器编写代码;由于ATMega128没有硬件乘法器或分频器,因此这些操作必须在软件中完成,并且它们占用相当多的周期.但是,为了代码的可移植性和易用性,我宁愿不将预先计算的值硬编码到我的代码中.例如,我有许多依赖于系统时钟频率的任务.目前我的运行频率为16MHz,但我应该选择降低它,比如降低电池应用的功耗,我想改变一行代码而不是多行代码.

那么说,C预处理器可以计算算术表达式,然后将结果“粘贴”到我的代码中,而不是将原始表达式“粘贴”到代码中吗?如果是这样,我该怎么做呢?他们的编译器选项和我需要考虑的是什么?

注意:我想要计算的值是常量值,所以我没有理由认为这不是一个特征.

最佳答案
这是一个问题:

> Q1. C预处理器可以执行算术吗?

这是另一个:

> Q2. C预处理器可以计算算术表达式然后“粘贴”
将结果存入我的代码而不是将原始表达式“粘贴”到代码中?

Q1的答案是肯定的. Q2的答案是否定的.两个事实都可以说明
使用以下文件:

foo.c的

#define EXPR ((1 + 2) * 3)
#if EXPR == 9
int nine = EXPR;
#else
int not_nine = EXPR;
#endif

如果我们将它传递给C预处理器,可以通过cpp foo.c或
等价的是gcc -E foo.c,我们看到的输出如下:

# 1 "foo.c"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 30 "/usr/include/stdc-predef.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/bits/predefs.h" 1 3 4
# 31 "/usr/include/stdc-predef.h" 2 3 4
# 1 "<command-line>" 2
# 1 "foo.c"


int nine = ((1 + 2) * 3);

预处理器保留定义int 9和9的行的事实
已经删除定义not_nine的行告诉我们它已正确执行
评估#if EXPR == 9所需的算术.

事实上,定义的预处理文本是int 9 =((1 2)* 3);
告诉我们#define指令导致预处理器被替换
EXPR的定义((1 2)* 3),而不是算术值
它的定义,9.

除了#define之外,C预处理器是否还有其他指令
影响?没有.

但这当然并不意味着int 9的定义必然需要a
运行时计算,因为编译器几乎肯定会评估
算术表达式((1 2)* 3)在编译时将其替换为
常数9.

我们可以通过检查编译器来查看编译器如何翻译源文件
编译目标文件.大多数工具链都会提供类似GNU binutils的东西
objdump协助这个.如果我用gcc编译foo.c:

gcc -c -o foo.o foo.c

然后调用:

objdump -s foo.o

看到foo.o的全部内容,我得到:

foo.o:     file format elf64-x86-64

Contents of section .data:
 0000 09000000                             ....            
Contents of section .comment:
 0000 00474343 3a202855 62756e74 752f4c69  .GCC: (Ubuntu/Li
 0010 6e61726f 20342e38 2e312d31 30756275  naro 4.8.1-10ubu
 0020 6e747539 2920342e 382e3100           ntu9) 4.8.1.

在.data部分中有希望的9硬编码.

请注意,预处理器的算术功能仅限于整数运算

转载注明原文:C预处理器可以执行算术吗?如果是,如何执行算术? - 代码日志