0

I try to make makro which should swap values in parameters. My code:

#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;
}

I'm new in C++ and can anyone tell me why can't I make it like that?

Cleo
  • 27
  • 4
  • 4
    Why a macro? Why not simply `std::swap`? – leemes Mar 13 '16 at 14:12
  • 3
    And what should `swap(2, 4)` result in? These are no variables, so they can't be swapped at all. Would you like to change what `2` and `4` mean in the rest of the code? – leemes Mar 13 '16 at 14:13
  • 1
    This macro is very error prone. There are many cases how it will fail to compile. – πάντα ῥεῖ Mar 13 '16 at 14:13
  • Macros are simple __text substitution__. If you write the content of the macro where you invoke it, you'll quickly see why it doesn't work. – Emil Laine Mar 13 '16 at 14:14
  • My task is like that: Make macro "swap" which will be swaping two values.. I don't know, so is that possible? Maybe Should I make method but is it include to my task? – Cleo Mar 13 '16 at 14:17
  • 1
    @Cleo What would you expect to be the result of `swap(2,4);` actually? That 4 is the new 2 now and vice versa? You should discuss that with some experienced mathematicians thoroughly. – πάντα ῥεῖ Mar 13 '16 at 14:22
  • @Cleo That makes more sense, yes. But anyways using a macro to do that isn't a very good idea. – πάντα ῥεῖ Mar 13 '16 at 14:37
  • Okay, I don't have contact with my teacher and I can't ask him about it. So if std::swap is not a good answer, are there any alternatives with using macros? – Cleo Mar 13 '16 at 14:41
  • 1
    For numeric types, you could have a look at [this answer for C](http://stackoverflow.com/questions/3982348/implement-generic-swap-macro-in-c). However, it is simply a horrible idea to use such a macro in C++, since it is very error prone. – leemes Mar 13 '16 at 15:08
  • @πάνταῥεῖ - back in the olden days of FORTRAN you could actually do something like that. Constants were held in modifiable data locations, so if you got yourself tangled up you could end up changing the value of 2 to 4. – Pete Becker Mar 13 '16 at 15:31

3 Answers3

3

You can't do it because when the macro is expanded the "arguments" are replaced as is. So your macro when expanded will look like

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

In other words, you try to assign values to a value, which makes no sense.

One solution is to use variables instead, but the one I recommend is to avoid using preprocessor macros for this to begin with, and instead create an inline function which does this "properly". Or, you know, just use std::swap.

Oh and another thing: You say you want to "swap two numbers in preprocessor". That's impossible. The preprocessor doesn't do anyhing, it just replaces the macro invocation with the body of the macro, to create code that the compiler sees and compiles into executable code, so the calculation you do is done at run-time anyway. If you want to do something at compile-time (but not by the preprocessor) then you should look into templates and constexpr.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
3

std::swap does what you want.

If your task really is to write a macro for that, write one which uses that function. But be prepared that your teacher might not like this solution.

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

If you want to avoid using std::swap, you can also assign the tuple (x, y) to (y, x):

#define swap(x, y) std::tie(y, x) = std::make_tuple(x, y)
leemes
  • 44,967
  • 21
  • 135
  • 183
  • Okay, thanks but.. it is for integer, yeah. Is that working for every kind of variable withoud caste? – Cleo Mar 13 '16 at 14:23
  • It works for every type which can be reassigned new values. So yeah, pretty much everything. – leemes Mar 13 '16 at 14:23
  • @Cleo So the question stays, why do you need to wrap that into a macro at all? – πάντα ῥεῖ Mar 13 '16 at 14:27
  • 1
    @πάνταῥεῖ I guess it's an exercise of a C teacher teaching C++, like so damn often. If I were in such a class, I'd teach the teacher by handing in the first solution from my answer, maybe adding a comment ranting about macros. ;) – leemes Mar 13 '16 at 14:28
  • Yeah.. `std::swap` is okay but I said that under.. It is my second C++ lesson, do you think that it should be answer? Isn't it to hard for that "lesson level"? – Cleo Mar 13 '16 at 14:48
1

I am not sure what the question is, but you should consider that computers in general don't work on proper mathematical concepts, but something much more restricted. When you use an int, it is not an integer, but a variable that holds a value in some restricted range (int is often 32bit, signed, two's complement, holding values -231 to 231-1).

While in mathematical terms the transformation you did makes sense, there are many combinations of a and b for which the expression a*b will fall out of the range representable by int. The behavior is undefined in the C++ language, but assuming you were accessing the hardware directly, in current processors it will wrap around and produce a number within the valid range, yet one that does not hold the mathematical value a*b. The rest of the operations will be starting from the wrong value and yield wrong results.

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489