编译器:MPLABX IDE V5.30
操作系统:Windows 10
我想做的是定义一些常量值(以便将来的更改更容易)并在预处理期间通过算术运算创建一些其他常量。然后在运行时使用这些常量。
这是我的意图的示例版本;
#include <stdio.h>
#include <math.h>
#define foo 100 // In case you change FOO in circuit, change this too!
#define bar (sqrt(foo))
int main(void) {
if ( bar > user_input)
{
do();
}
}
问题是,我想,由于输入是一个常量值,定义的东西将由编译器计算,并且
bar
将被10
代替,而不是(sqrt(foo))
。但当我编译它时,数据和程序大小发生了巨大的变化。当我拆开它时,有大量的说明,而不是简单地直接放一个数字。
然后我按照另一个问题的答案的建议并放置了一个 const
squareroot()
函数和 const int
声明,但编译器给出了类似的警报;
main.c:50:38: error: initializer element is not a compile-time constant
这是第二次尝试;
#include <stdio.h>
#include <squareroot.h>
#define foo 100 // In case you change FOO in circuit, change this too!
const int bar = squareroot(foo);
int main(void) {
if ( bar > user_input)
{
do();
}
}
const int squareroot(const int input)
{
do()
}
我如何向编译器表达自己的意思,使其理解代码中的某些行在运行时发生的情况下都是不变的,以便它可以进行算术运算,而不是简单地将标记/文本传递给函数体?
#define
是纯文本替换,仅此而已。所有 #define
转换都发生在预处理翻译阶段,即在对表达式等进行任何分析之前。
编译器必须在常量表达式中支持哪些表达式的列表可以在当前 C 标准的第 6.6 节中找到,有关摘要请参阅此处。不包括调用函数。
(当然,个别编译器可能会提供标准不需要的功能)。
如果您必须使用不支持在常量表达式中调用浮点函数
sqrt
的编译器,那么您的选择包括:
main
函数开始时初始化的全局变量。大多数不错的编译器都会为你做这件事
#define foo 100 //in case you change FOO in circuit, change this too!
#define bar (sqrt(foo))
volatile int x;
int main(void) {
x = bar;
}
结果:
x:
.zero 4
main:
push rbp
mov rbp, rsp
mov DWORD PTR x[rip], 10
mov eax, 0
pop rbp
ret
唯一的问题是 MPLAB 是否是一个不错的编译器。至少在免费版本中不是这样。 Microchip 故意使生成的代码变得更糟,以迫使您做出购买决定。如果您决定使用 PIC uC,您就没有机会只购买该“产品”。
您可以反过来解决问题。 您知道编译器无法处理函数,但所有编译器都可以处理乘法。 由于 sqrt(x)*sqrt(x) = x
#define bar (10)
const int foo = bar * bar;
这将为您提供任何编译器上 foo 的编译时间常数。 不幸的是,我不知道如何将 XC8 编译器的输出粘贴到 Web 浏览器,因此我无法向您展示结果。 或者,不要费心#define。
const int bar = 10;
const int foo = bar * bar;
如果必须修补代码,在调试过程中,只需修补 bar 和 foo 的值即可。 对于#define,您需要在使用#define 的地方进行修补。 如果 foo 是一个数字,导致 bar 成为浮点数,那么您将必须执行这两个值
const int bar = 9;
const int foo = 90; /* bar * bar */