C 预处理器可以执行整数运算吗?

发布于 2024-08-07 19:35:42 字数 191 浏览 2 评论 0原文

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

心作怪 2024-08-14 19:35:42

整数算术?运行以下程序来找出答案:

#include "stdio.h"
int main() {
    #if 1 + 1 == 2
        printf("1+1==2\n");
    #endif
    #if 1 + 1 == 3
        printf("1+1==3\n");
    #endif
}

答案是“是”。有一种方法可以让预处理器执行整数运算,即在预处理器条件中使用它。

但请注意,您的示例不是整数算术。我刚刚检查过,如果您尝试使其进行浮点比较,GCC 的预处理器就会失败。我还没有检查标准是否允许在预处理器中使用浮点运算

常规宏扩展不会计算整数表达式。它将它留给编译器,通过预处理可以看出 ( -E(GCC 中))如下:

#define ONEPLUSONE (1 + 1)
#if ONEPLUSONE == 2
   int i = ONEPLUSONE;
#endif

结果是 int i = (1 + 1); (可能还加上一些指示源文件名和行号等的内容)。

Integer arithmetic? Run the following program to find out:

#include "stdio.h"
int main() {
    #if 1 + 1 == 2
        printf("1+1==2\n");
    #endif
    #if 1 + 1 == 3
        printf("1+1==3\n");
    #endif
}

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:

#define ONEPLUSONE (1 + 1)
#if ONEPLUSONE == 2
   int i = ONEPLUSONE;
#endif

The result is int i = (1 + 1); (plus probably some stuff to indicate source file names and line numbers and such).

奈何桥上唱咆哮 2024-08-14 19:35:42

您编写的代码实际上并不使预处理器进行任何计算。 #define 执行简单的文本替换,因此定义后:

#define PI 3.1416
#define OP PI/100

此代码:

if (OP == x) { ... }

变为

if (3.1416/100 == x) { ... }

然后编译。编译器反过来可能会选择采用这样的表达式并在编译时对其进行计算,并生成与此等效的代码:

if (0.031416 == x) { ... }

但这是编译器,而不是预处理器。

为了回答你的问题,是的,预处理器可以做一些算术。当你写这样的东西时可以看到这一点:

#if (3.141/100 == 20)
   printf("yo");
#elif (3+3 == 6)
   printf("hey");
#endif

The code you wrote doesn't actually make the preprocessor do any calculation. A #define does simple text replacement, so with this defined:

#define PI 3.1416
#define OP PI/100

This code:

if (OP == x) { ... }

becomes

if (3.1416/100 == x) { ... }

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:

if (0.031416 == x) { ... }

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:

#if (3.141/100 == 20)
   printf("yo");
#elif (3+3 == 6)
   printf("hey");
#endif
芸娘子的小脾气 2024-08-14 19:35:42

是的,可以使用 Boost 预处理器来完成。而且它与纯 C 兼容,因此您可以在仅 C 编译的 C 程序中使用它。不过,您的代码涉及浮点数,所以我认为这需要间接完成。

#include <boost/preprocessor/arithmetic/div.hpp>
BOOST_PP_DIV(11, 5) // expands to 2
#define KB 1024
#define HKB BOOST_PP_DIV(A,2)
#define REM(A,B) BOOST_PP_SUB(A, BOOST_PP_MUL(B, BOOST_PP_DIV(A,B)))
#define RKB REM(KB,2)

int div = HKB;
int rem = RKB;

此预处理为(检查 gcc -S):

int div = 512;
int rem = 0;

感谢这个问题

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.

#include <boost/preprocessor/arithmetic/div.hpp>
BOOST_PP_DIV(11, 5) // expands to 2
#define KB 1024
#define HKB BOOST_PP_DIV(A,2)
#define REM(A,B) BOOST_PP_SUB(A, BOOST_PP_MUL(B, BOOST_PP_DIV(A,B)))
#define RKB REM(KB,2)

int div = HKB;
int rem = RKB;

This preprocesses to (check with gcc -S):

int div = 512;
int rem = 0;

Thanks to this question.

腹黑女流氓 2024-08-14 19:35:42

是的。

我不敢相信还没有人与某个混淆的 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.

红衣飘飘貌似仙 2024-08-14 19:35:42

进行算术运算时要小心:添加括号

#define SIZE4 4
#define SIZE8 8
#define TOTALSIZE SIZE4 + SIZE8

如果你曾经使用过类似的东西:

unsigned int i = TOTALSIZE/4;

并且期望i为3。你会得到4 + 2 = 6。

添加括号:

#define TOTALSIZE (SIZE4 + SIZE8)

Be careful when doing arithmetic: add parentheses.

#define SIZE4 4
#define SIZE8 8
#define TOTALSIZE SIZE4 + SIZE8

If you ever use something like:

unsigned int i = TOTALSIZE/4;

And expect i to be 3. You would get 4 + 2 = 6 instead.

Add parentheses:

#define TOTALSIZE (SIZE4 + SIZE8)
甜心小果奶 2024-08-14 19:35:42

人们可以通过使用条件定义来实现诸如预处理器算术之类的功能。应该为每个(可能的/支持的)输入值有条件地定义输出值。当然可以生成这样的定义列表以使生活更轻松,这是一个简单的示例:

static_log2.h:

#if STATIC_LOG2_ARG & (1 << 31)
#define STATIC_LOG2_VALUE 31
 
#elif STATIC_LOG2_ARG & (1 << 30)
#define STATIC_LOG2_VALUE 30
 
/* Other values here */

#elif STATIC_LOG2_ARG & (1 << 1)
#define STATIC_LOG2_VALUE 0
 
#else
#error "Invalid STATIC_LOG2_ARG value."
#endif

用法如下:

test.c:

#define STATIC_LOG2_ARG 89
#include static_log2.h
char myarray[STATIC_LOG2_VALUE]; // sizeof(myarray) == 6

它看起来像它看起来的那样,我认为这是一个有趣的事实比好的做法。也许这可以用更优雅的方式来完成,但你明白了。

基于 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:

#if STATIC_LOG2_ARG & (1 << 31)
#define STATIC_LOG2_VALUE 31
 
#elif STATIC_LOG2_ARG & (1 << 30)
#define STATIC_LOG2_VALUE 30
 
/* Other values here */

#elif STATIC_LOG2_ARG & (1 << 1)
#define STATIC_LOG2_VALUE 0
 
#else
#error "Invalid STATIC_LOG2_ARG value."
#endif

And the usage will be like:

test.c:

#define STATIC_LOG2_ARG 89
#include static_log2.h
char myarray[STATIC_LOG2_VALUE]; // sizeof(myarray) == 6

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文