为什么我的C程序会输出这个?

3

我正在尝试解决两个与预处理器相关的问题,但在这两个程序中,我得到了一些结果,我无法弄清楚如何得到这些结果。以下是我的程序:

#include<stdio.h>
#define SQUARE(x) x*x
int main()
{
float s=10,u=30 ,t=2,a;
a=2*(s-u*t)/SQUARE(t);
printf("Result:%f\n",a);
return 0;
}

根据我的理解,这个程序的输出应该是-25.000,但我得到的是-100.000
第二个程序如下:
#define FUN(i,j) i##j
int main()
{
int val1 = 10;
int val12 = 20;
clrscr();
printf("%d\n",FUN(val1,2));
getch();
}

输出应该是 102,但我得到的是 20; 为什么会这样?

我怀疑 #include>stdio.h> 甚至能否编译... - PhiLho
抱歉 @PhiLho,它是 #include<stdio.h>。 - Amit Singh Tomar
你的第二个例子无法编译。请复制/粘贴您使用的确切源代码。 - Alexandre C.
@Alexandrie,我在粘贴代码时犯了一个错误,现在已经更正过来了。 - Amit Singh Tomar
4个回答

11
#define SQUARE(x) x*x

应该是

#define SQUARE(x) ((x)*(x))

实际上,不加括号的话,2*(s-u*t)/SQUARE(t)会被展开为

2*(s-u*t)/t*t

被解释成

(2*(s-u*t)/t)*t

关于你的第二个问题,根据##运算符的语义,FUN(val1,2)会被扩展为val12。但你的意图仍不清楚:这个printf语句可能会被理解为

printf("%d\n", val12);

这将打印出20


同样地,例如第二个例子,(i##j) - alternative
谢谢@Alexandre。这个表达式 a=(2*(s-u*t)/t)t; 是根据 #define SQUARE(x) xx 定义的,这就是你想要说的内容。 - Amit Singh Tomar
为什么像这样定义FUN:#define FUN(i,j) (i##j) 就可以解决问题呢? - SivGo
@SivGo:第二个示例的意图不清楚。现在OP已经更正了代码,我会更新答案。 - Alexandre C.

4

第一个:

a=2*(s-u*t)/SQUARE(t);

替换宏定义后,我们得到:

a=2*(s-u*t)/t*t;

现在,由于在SQUARE的定义中没有(),所以我们得到:

a=2*(10-30*2)/2*2; --> a=2*(-50)/2*2; --> a=-100/2*2; --> a=-50*2; --> a=-100

如果你想得到-25,你应该将SQUARE(x)定义为(x*x)

编辑:关于第二个示例添加解释。

printf("%d\n"FUN(val1,2));

再次强调,我们首先应该替换define(提醒:##“连接”定义的字符串-我无法找到完美的措辞来解释它,因此请看下面的示例...):

printf("%d\n",val12);  [note: the comma (,) is missing - so it won't compile.]

因为val12的值是20,所以你会得到这个值。

这两个例子的重点是要记住我们应该先处理定义(因为在“现实生活”中编译器(或预处理器)在运行时之前就已经完成了它)。

希望这能有所帮助。


感谢@SivGo的解释,也感谢事实证明“/*”运算符的结合性是从左到右的。 - Amit Singh Tomar
还没有解决第二个问题。 - Amit Singh Tomar
printf("%d\n",FUN(val1,2)); 这里val1的值不会被替换为10吗?这就是我感到困惑的地方...我认为它应该被替换为10... - Amit Singh Tomar
第一阶段是处理定义,然后再用其值“替换”变量名,因此在到达该点时,val1已经不存在了,只有val12。 - SivGo
明白了,这是在编译之前的预处理工作。 - Amit Singh Tomar

3

对于第一个案例,

a=2*(s-u*t)/SQUARE(t);

would translate to

a=2*(s-u*t)/t*t;

在编译时处理。这是使用预处理器时常见的错误。

0

我知道我来晚了,但我有完美的答案。

在C#中,define用于调用函数参数中的文本,

例如,#define hai(s1) printf("%s=%s",#s1,s1);

       in main: i am calling as hai(tom); tom was initialized as "india" string.

这个程序的输出是tom=india,调用字符串tom是通过#打印出来的。

类似地,##用于从函数参数中获取文本并将它们连接起来,返回连接标识符的值。

上面的程序有两个参数va1和2,传递给i和j。然后将va1和2连接起来形成va12。

va12是可用值为20的标识符。这就是为什么返回20的原因。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接