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

Sch*_*him 22 c-preprocessor

正如问题所说,C预处理器能够做到吗?

例如:

#define PI 3.1416
#define OP PI/100
#define OP2 PI%100
Run Code Online (Sandbox Code Playgroud)

OP和/或OP2在预处理阶段是否有任何计算方法?

Ste*_*sop 30

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

#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
 }
Run Code Online (Sandbox Code Playgroud)

答案是"是",有一种方法可以使预处理器执行整数运算,即在预处理器条件下使用它.

但请注意,您的示例不是整数算术.我刚检查过,如果你试图让它进行浮点比较,gcc的预处理器就会失败.我没有检查标准是否允许预处理器中的浮点运算.

常规宏扩展不会计算整数表达式,而是将它留给编译器,可以通过预处理(-E in gcc)看到以下内容:

#define ONEPLUSONE (1 + 1)
#if ONEPLUSONE == 2
    int i = ONEPLUSONE;
#endif
Run Code Online (Sandbox Code Playgroud)

结果是int i = (1 + 1);(加上可能表示源文件名和行号等的东西).

  • 哦,不,我刚刚意识到克里斯一定有什么意思!由于SO格式代码的方式,我的程序*没有终止换行符*!这甚至不是编译器必须诊断的无效程序,它是未定义的行为.恐怖,惊慌和一般的恐慌!我必须马上解决它.`; -p` (23认同)
  • @Chris:一个紧密的大括号,达到"返回值0"(5.1.2.2.3,程序终止).如果我不允许在标记为"C"的问题中采用标准C,那么世界将会发生什么?难道你找不到在C89编译器可能看到的代码中使用//样式注释的人,而是抱怨它们吗?;-) (13认同)
  • 克里斯:我们现在生活在未来,虽然飞行汽车仍然缺失,但主要功能的默认返回值已经到了! (9认同)

sho*_*osh 19

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

#define PI 3.1416
#define OP PI/100
Run Code Online (Sandbox Code Playgroud)

这段代码:

if (OP == x) { ... }
Run Code Online (Sandbox Code Playgroud)

if (3.1416/100 == x) { ... }
Run Code Online (Sandbox Code Playgroud)

然后它被编译.反过来,编译器可以选择采用这样的表达式并在编译时计算它并生成与此等效的代码:

if (0.031416 == x) { ... }
Run Code Online (Sandbox Code Playgroud)

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

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

#if (3.141/100 == 20)
   printf("yo");
#elif (3+3 == 6)
   printf("hey");
#endif
Run Code Online (Sandbox Code Playgroud)

  • 遗憾的是,如果您尝试条件编译片段,则会收到来自GCC的消息:`xc:5:6:错误:预处理器表达式中的浮动常量`.你可以用C预处理器进行整数运算; 你不能用它做浮点运算. (5认同)
  • 看起来 gcc 在这里偷工减料,Stroustrup C++ 第 2 版 r.16.5 `#if 常量表达式`、`r.5.19 常量表达式`:“...浮点常量必须转换为整型”。 (4认同)

pmg*_*pmg 7

是的,我的意思是:它可以做算术:)

99瓶啤酒中所示.


hig*_*dth 7

是的,可以使用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;
Run Code Online (Sandbox Code Playgroud)

这个预处理(用gcc -S检查)

int div = 512;
int rem = 0;
Run Code Online (Sandbox Code Playgroud)

感谢这个帖子.


Phi*_*hil 7

做算术时要小心:加括号

#define SIZE4 4
#define SIZE8 8
#define TOTALSIZE SIZE4 + SIZE8
Run Code Online (Sandbox Code Playgroud)

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

unsigned int i = TOTALSIZE/4;
Run Code Online (Sandbox Code Playgroud)

预计i为 3。您会得到 4 + 2 = 6。

添加括号:

#define TOTALSIZE (SIZE4 + SIZE8)
Run Code Online (Sandbox Code Playgroud)


Ste*_*non 5

是的。

我不敢相信还没有人与某个模糊的 C 竞赛获胜者联系起来。这家伙通过递归包含在预处理器中实现了 ALU。 是实现,这里有一些解释。

现在,也就是说,你不想做那个人所做的。这很有趣,但请查看他的提示文件中的编译时间(更不用说生成的代码无法维护的事实)。更常见的是,人们严格地将预处理器用于文本替换,并且常量整数算法的计算发生在编译时或运行时。

然而,正如其他人所指出的,您可以在 #if 语句中进行一些算术运算。

  • http://stackoverflow.com/questions/652788/what-is-the-worst-real-world-macros-pre-processor-abuse-youve-ever-come-across/1242177#1242177 - Chaos-pp。预处理器滥用风格。 (2认同)