【问题标题】:How to swap two numbers in preprocessor?如何在预处理器中交换两个数字?
【发布时间】:2016-03-13 14:05:13
【问题描述】:

我尝试制作应该交换参数值的 makro。我的代码:

#include <iostream>

using namespace std;

#define swap(x,y)     \
x = x * y;              \
y = x / y;              \
x = x / y;              

int main() {

    int a = 1;
    int b = 2;

    swap(a,b);

    cout << "a: " << a << ", b: " << b << endl; // a = 2 and b = 1

    system("pause");
    return 0;
}

我是 C++ 新手,谁能告诉我为什么我不能那样做?

【问题讨论】:

  • 为什么是宏?为什么不简单地std::swap
  • swap(2, 4) 会产生什么结果?这些不是变量,因此根本无法交换。您想更改其余代码中24 的含义吗?
  • 这个宏很容易出错。编译失败的情况很多。
  • @Cleo 您希望swap(2,4); 的实际结果是什么?那4现在是新的2,反之亦然?你应该和一些有经验的数学家彻底讨论。
  • 对于数字类型,您可以查看this answer for C。然而,在 C++ 中使用这样的宏简直是一个可怕的想法,因为它很容易出错。

标签: c++


【解决方案1】:

您不能这样做,因为当宏展开时,“参数”会被替换原样。所以你的宏在展开后会是这样的

2 = 2 * 4;
4 = 2 / 4;
2 = 2 / 4;

换句话说,您尝试将值分配给一个值,这是没有意义的。

一种解决方案是改用变量,但我推荐的一种方法是避免使用预处理器宏,而是创建一个“正确”执行此操作的inline 函数。或者,您知道,只需使用std::swap

哦,还有一件事:你说你想“在预处理器中交换两个数字”。这不可能。预处理器不做任何事情,它只是用宏的主体替换宏调用,以创建编译器看到的代码并编译成可执行代码,因此无论如何您所做的计算都是在运行时完成的。如果你想在编译时做某事(而不是通过预处理器),那么你应该查看 templatesconstexpr

【讨论】:

  • @Cleo 函数怎么样?
  • 好的,但我必须在宏中完成该任务,我不能使用第三个值。这可能吗?
  • @Cleo 如果您必须使用扩展为代码的宏以仅使用实际值交换值(我猜是学校作业?)那么您需要想出另一种不赋值的方式。
【解决方案2】:

std::swap 做你想做的事。

如果您的任务确实是为此编写一个宏,请编写一个使用该函数的宏。但请做好准备,您的老师可能不喜欢这种解决方案。

#define swap(x, y) std::swap(x, y)

如果要避免使用std::swap,也可以将元组(x, y)赋值给(y, x)

#define swap(x, y) std::tie(y, x) = std::make_tuple(x, y)

【讨论】:

  • 好的,谢谢,但是.. 它是整数,是的。这适用于没有种姓的每一种变量吗?
  • 它适用于可以重新分配新值的每种类型。所以,是的,几乎所有东西。
  • @Cleo 所以问题仍然存在,为什么你需要将它包装到一个宏中?
  • @πάνταῥεῖ 我猜这是一个 C 老师教 C++ 的练习,就像该死的经常一样。如果我在这样的课上,我会通过提交我的答案中的第一个解决方案来教老师,也许会添加一个关于宏的评论。 ;)
  • 是的.. std::swap 还可以,但我说在下面.. 这是我第二节 C++ 课,你认为应该回答吗?那个“课级”不是很难吗?
【解决方案3】:

我不确定问题是什么,但您应该考虑到计算机通常不能处理正确的数学概念,而是受到更多限制。当您使用int 时,它不是一个整数,而是一个在某个受限范围内保存值的变量(int 通常是 32 位,有符号,二进制补码,保存值 -231 到 231-1)。

虽然从数学角度来说,您所做的转换是有意义的,但 ab 的许多组合中,表达式 a*b 将超出 int 可表示的范围。这种行为在 C++ 语言中是未定义的,但假设您直接访问硬件,在当前处理器中它将环绕并生成一个有效范围内的数字,但该数字不包含数学值 a*b。其余的操作将从错误的值开始并产生错误的结果。

【讨论】:

    猜你喜欢
    • 2014-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-25
    • 2020-05-29
    • 2020-06-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多