-1

我已经定义了以下宏,

#define abss(a) a >= 0 ? a : -a

在调用它时,

int b=-1;
int c = abss(b);
printf("%d\n",c);

它应该以 b >= 0 的形式替换?b : --b,它应该输出 -2,但它在我的 Bloodshed/DevC++ 编译器 1 中输出。

我正在分析 C 语言以进行考试,所以我必须知道在 C 中上述情况实际发生了什么。输出结果 1 是针对我正在使用的 CPP 编译器还是什么?

4

7 回答 7

3

你的代码

int b=-1;
int c = abss(b);
printf("%d\n",c);

被预处理器翻译成:

int b=-1;
int c = b >= 0 ? b : -b;
printf("%d\n",c);

int b=-1在 C 域中,而在abss(b)编译器到达之前由预处理器扩展int b=-1

于 2012-06-26T10:41:44.587 回答
2

为什么你认为它应该输出-2?

#define abss(a) a >= 0 ? a : -a

所以这个: int c = abss(b)

变成 int c = b >= 0 ?乙:-乙

b 为 -1,因此计算结果为 1

顺便说一句,您应该将宏参数的每次使用都括起来,因为您可能会传递诸如 x + 1 之类的东西。这会很奇怪。

更不用说 abss(++x) 的结果了

于 2012-06-26T10:46:01.223 回答
1

这个宏

#define abss(a) a >= 0 ? a : -a

确实是危险的,但危险并不在你认为的地方。你帖子里的表情

int c = abss(b);

工作得很好。然而,考虑一下当表达式不是一个简单的变量,而是一个难以计算的函数,或者当它是一个有副作用的表达式时会发生什么。例如

int c = abss(long_calc(arg1, arg2));

或者

int c = abss(ask_user("Enter a value"));

或者

int c = abss(b++);

如果abss是一个函数,那么所有三个调用都会在可预测的时间内产生良好的结果。但是,该宏使第一次调用调用long_calcask_user两次(如果用户在再次提示时输入不同的数字怎么办?),并且它后增量b两次。

此外,考虑这个看似简单的表达式:

int c = abss(b) + 123;

由于+具有比 更高的优先级? :,因此生成的扩展将如下所示:

int c = b >= 0 ? b : -b + 123;

whenb是肯定的,123不会加,所以表达的意思会发生巨大的变化!

最后一个缺点可以通过将表达式括在括号中来解决。您还应该将每个宏参数括在括号中,如下所示:

 #define abss(a) ((a) >= 0 ? (a) : -(a))
于 2012-06-27T18:32:45.287 回答
1

宏处理器永远不会将两个相邻的标记连接在一起,即使它们之间没有空格,所以确实,正如其他海报所提到的,你的宏扩展为- b, 或1.

如果您希望两个标记在被预处理器扩展时变成一个,则必须使用标记粘贴运算符 ##,例如

#define abss(a) a >= 0 ? a : - ## a

这确实会做你想做的事,因为负号和变量将形成一个标记。不幸的是(或幸运的是,取决于你如何看待它!)粘贴的标记“-b”将无效,并且扩展将无法编译。

于 2012-06-26T10:44:09.880 回答
1
#define neg(a) -a

int b = -1;
neg(b);

在上面的例子中,宏被-b预处理器扩展,这将导致值为 1。预处理器甚至不会知道内容的符号b是负数,那么第二个应该-从哪里来形成前缀递减运算符?

即使你这样写:

 neg( -b );

宏替换是在令牌级别完成的,而不是作为文本搜索和替换。你会得到相当于- ( -b ),但不是 --b

编辑:您在其他评论中链接到的手册已经过时(甚至没有解决 C99 标准),而且非常糟糕。只是浏览了一下,我发现了半打陈述,如果你认为它们是正确的,它们会让你看起来真的很愚蠢。不要使用它,除了生火。

于 2012-06-26T10:38:04.007 回答
1

您的宏扩展为

b >= 0 ? b : -b;

不要b >= 0 ? b : --(-b);或任何你所期望的。

你是在暗示

int x = -4;
-x; 

应该减少x吗?

底线- 尽可能避免使用宏。

于 2012-06-26T10:40:15.337 回答
0

你得到这种行为的原因是预处理器只会用 b 替换 a ,所以你的代码在预处理后会很有效

b >= 0 ? b : -b

并不是

b >= 0 ? b : --b

因此,当 b = -1 时,它实际上将被视为 -(-1) 并因此变为 1。

您可以检查预处理器输出并亲自查看。

于 2012-06-26T10:47:21.917 回答