C 预处理器可以执行整数运算吗?
C 预处理器能够执行整数算术吗?
例如:
#define PI 3.1416
#define OP PI/100
#define OP2 PI%100
有没有办法在预处理阶段计算 OP
和/或 OP2
?
Is the C preprocessor able to perform integer arithmetic?
E.g.:
#define PI 3.1416
#define OP PI/100
#define OP2 PI%100
Is there a way OP
and/or OP2
get calculated in the preprocessing phase?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
整数算术?运行以下程序来找出答案:
答案是“是”。有一种方法可以让预处理器执行整数运算,即在
预处理器条件
中使用它。但请注意,您的示例不是整数算术。我刚刚检查过,如果您尝试使其进行
浮点比较
,GCC 的预处理器就会失败。我还没有检查标准是否允许在预处理器中使用浮点运算。常规宏扩展不会计算
整数表达式
。它将它留给编译器,通过预处理可以看出 ( -E(GCC 中))如下:结果是
int i = (1 + 1);
(可能还加上一些指示源文件名和行号等的内容)。Integer arithmetic? Run the following program to find out:
The answer is "yes". There is a way to make the preprocessor perform integer arithmetic, which is to use it in a
preprocessor condition
.Note however that your examples are not integer arithmetic. I just checked, and GCC's preprocessor fails if you try to make it do
float comparisons
. I haven't checked whether the standard ever allows floating point arithmetic in the preprocessor.Regular macro expansion does not evaluate
integer expressions
. It leaves it to the compiler, as can be seen by preprocessing (-E in GCC) the following:The result is
int i = (1 + 1);
(plus probably some stuff to indicate source file names and line numbers and such).您编写的代码实际上并不使预处理器进行任何计算。 #define 执行简单的文本替换,因此定义后:
此代码:
变为
然后编译。编译器反过来可能会选择采用这样的表达式并在编译时对其进行计算,并生成与此等效的代码:
但这是编译器,而不是预处理器。
为了回答你的问题,是的,预处理器可以做一些算术。当你写这样的东西时可以看到这一点:
The code you wrote doesn't actually make the preprocessor do any calculation. A #define does simple text replacement, so with this defined:
This code:
becomes
and then it gets compiled. The compiler in turn may choose to take such an expression and calculate it at compile time and produce a code equivalent to this:
But this is the compiler, not the preprocessor.
To answer your question, yes, the preprocessor CAN do some arithmetic. This can be seen when you write something like this:
是的,可以使用 Boost 预处理器来完成。而且它与纯 C 兼容,因此您可以在仅 C 编译的 C 程序中使用它。不过,您的代码涉及浮点数,所以我认为这需要间接完成。
此预处理为(检查
gcc -S
):
感谢这个问题 。
Yes, it can be done with the Boost Preprocessor. And it is compatible with pure C, so you can use it in C programs with C-only compilations. Your code involves floating-point numbers though, so I think that needs to be done indirectly.
This preprocesses to (check with
gcc -S
):Thanks to this question.
是的。
我不敢相信还没有人与某个混淆的 C 竞赛获胜者建立联系。这个家伙通过递归包含在预处理器中实现了 ALU。 这里是实现,这里是实现。 us.ioccc.org/2004/vik2.hint" rel="noreferrer">这里有一些解释。
现在,也就是说,你不想做那个人所做的事情。这很有趣,但是看看他的提示文件中的编译时间(更不用说生成的代码是不可维护的)。更常见的是,人们严格使用预处理器进行文本替换,并且常整数算术的评估发生在编译时或运行时。
然而,正如其他人指出的,您可以在 #if 语句中进行一些算术运算。
Yes.
I can't believe that no one has yet linked to a certain obfuscated C contest winner. The guy implemented an ALU in the preprocessor via recursive includes. Here is the implementation, and here is something of an explanation.
Now, that said, you don't want to do what that guy did. It's fun and all, but look at the compile times in his hint file (not to mention the fact that the resulting code is unmaintainable). More commonly, people use the pre-processor strictly for text replacement, and evaluation of constant integer arithmetic happens either at compile time or run time.
As others noted however, you can do some arithmetic in #if statements.
进行算术运算时要小心:添加括号。
如果你曾经使用过类似的东西:
并且期望
i
为3。你会得到4 + 2 = 6。添加括号:
Be careful when doing arithmetic: add parentheses.
If you ever use something like:
And expect
i
to be 3. You would get 4 + 2 = 6 instead.Add parentheses:
人们可以通过使用条件定义来实现诸如预处理器算术之类的功能。应该为每个(可能的/支持的)输入值有条件地定义输出值。当然可以生成这样的定义列表以使生活更轻松,这是一个简单的示例:
static_log2.h:
用法如下:
test.c:
它看起来像它看起来的那样,我认为这是一个有趣的事实比好的做法。也许这可以用更优雅的方式来完成,但你明白了。
基于 Ralf Holly 文章:approxion.com
One can achieve something like preprocessor arithmetic by usage of conditional defines. The output value should be conditionally defined for every (possible/supported) value of input(s). Such a list of defines can be of course generated to make life easier, here is a simple example:
static_log2.h:
And the usage will be like:
test.c:
It looks as it looks, I consider it as an interesting fact rather than good practice. Probably this could be done in a more elegant way, but you get the idea.
Based on Ralf Holly article: approxion.com