【问题标题】:Explanation needed for this pre-processor directive C/C++此预处理器指令/C++ 所需的说明
【发布时间】:2014-09-12 05:16:15
【问题描述】:

我试图在一些测试中解决这个问题,但后来当我在家里运行它时,它给出了意想不到的答案。 我无法理解这段代码:

#include <stdio.h>
#include <conio.h>
#define swap(a,b) temp=a; a=b; b=temp;
int main()
{
int i, j, temp;
i=5;
j=10;
temp=0;
if( i > j) //evaluates to false
swap( i, j );
printf( "%d %d %d", i, j, temp); //expected output: 5 10 0
getch();
return 0;
}

我得到的输出是:10 0 0

请有人解释它是如何工作的。

【问题讨论】:

  • 只是一个建议,避免coniogetch
  • 好的,我不会经常使用它们。
  • 另一个建议是永远不要写这样的宏,它们在很多方面都是不安全的。相反,请使用函数。

标签: c++ c


【解决方案1】:

代码如下

if( i > j) //evaluates to false
swap( i, j );

变成

if( i > j) //evaluates to false
temp=i; i=j; j=temp;

相当于

if( i > j) //evaluates to false
{temp=i;} i=j; j=temp;

如果条件为假,会出现以下意外结果

i=5;
j=10;
temp=0;
i=j;  /* i becomes 10 */
j=temp; /* j becomes 0 */

学习

  1. 尝试将块(if、else、for、do、while)放入{}
  2. 避免使用宏,更喜欢函数
  3. 如果必须使用宏,请使用安全宏,例如:

#define swap(a,b) do { temp=a; a=b; b=temp; } while(0)

注意有no terminating semicolon after while(0)

【讨论】:

  • 谢谢.. 我得到了丢失的链接。 :)
  • 我很高兴它有帮助:)
  • 现在你看到了一个宏观恐怖的例子,算出它扩展成什么:swap(a[i++], b[i++])
  • @Jerry101 无论 swap 是宏还是函数,该行都会产生未定义的行为...
  • @Lundin 可能他的意思是swap(a[i++], b[j++]),结果打错了
【解决方案2】:

展开宏,得到:

if (i > j)
   temp = i;
i = j;
j = temp;

这就是为什么经验丰富的 c 程序员将宏体包装在 do{...}while(0) 中的原因。

#define swap(a, b) do{temp=a; a=b; b=temp;}while(0)

【讨论】:

  • 如果您解释外部循环(强制分号终止),然后将 temp 带入本地范围,则会得到更多的布朗尼点。
  • 更多经验丰富的程序员使用内联函数而不是宏
  • 经验丰富的程序员也不会在if 后面省略大括号
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多