tags:

views:

456

answers:

5

How can one swap pointer addresses within a function with a signature?

Let's say:

int weight, height;
void swap(int* a, int* b);

So after going out of this function the addresses of the actual parameters (weight and height) would be changed. Is it possible at all?

+6  A: 

The new answer (since the question has been reformulated)

is that addressed of variables are determined at compile time and can therefore not be swapped. Pointers to variables however can be swapped.

Old answer: this was the answer when the question still implied swapping the values of 2 variables by means of a function:

function call:

 int width=10, height=20;
 swap(&width, &height)

implementation:

 void swap(int *a, int *b)
 {
      int temp;
      temp=*a;
      *a = *b;
      *b = temp;
 }

or...without using a temporary variable: ;^)

 void swap(int *a, int *b)
 {
      *a ^= *b;
      *b ^= *a;
      *a ^= *b;
 }

do watch out that the last method breaks for the case: swap (&a, &a). Very sharply pointed out by user9876 in the comments.

Toad
Thats C, not C++ and - if i may comment it - the last approach is less then intuitive.
RED SOFT ADAIR
redsoft: He has tagged the question both c and c++
Toad
red: intuitive or not...it's fast, and the name of the function clearly describes what is going on. One doesn't always need to understand the algorithm to be able to use it.
Toad
If you haven't seen XOR used to swap two variables then you've not advanced past the first lesson of computer science 101.
PP
pp: truth is that a lot of programmers today don't know jack about bit manipulation (apart from rudimentary if statements).
Toad
That XOR trick is nothing more than a bunch of wankers trying to be clever (and not really succeeding). You cannot say anything about its speed since it's not specified what it will compile into (any half-decent compiler will do it in registers anyway which will make the speed difference moot. and make the saving of a variable irrelevant). The greatest crime perpetrated on coders is cowboys writing hard-to-maintain software. Anyway, thanks for listening to my rant :-) Not voting anything up or down here since it's both irrelevant and a dupe many times over.
paxdiablo
Not having a go at you there, @reiner, I saw your smiley, and your first implementation works fine in C++ despite @Stefan's misgivings.
paxdiablo
I don't understand why anyone would use the XOR trick on modern processors. It will be slower. If the processor executes exactly what you wrote, then the XOR trick is 9 memory accesses but the simple method is only 4. On modern CPUs, memory accesses are much slower than anything else. If the compiler optimizes the XOR trick to store intermediate values in registers so there are only 4 memory accesses, then you still have 3 XOR operations that aren't needed in the simple solution. Also, a really smart compiler could inline the simple solution and it may generate no code at all.
user9876
user9876
hahaha... But at least we had a fun discussion in the comments about it! I agree that optimizations on this level are typically insane (if you need this level of detail switch to inline assembly). The age old wisdom is valid here: one never knows, without measuring.
Toad
user9876: very good point!
Toad
+6  A: 

In C++ you would write

 void swap(int *a, int *b)
 {
    std::swap(*a, *b);
 }

or rather just use:

 std::swap(a, b);
RED SOFT ADAIR
this is c++ only. His question is also tagged as c
Toad
Yeah, but that's an entirely different language. Since he's obviously a beginner, let's help him learn C++ and not get him confused. [Retagged].
MSalters
The title of this post is "...in c++", not in "c"
RED SOFT ADAIR
It was retagged c by someone other than the OP even though there was NO indication it was for C and EVERY indication it was C++. MSalters fixed that.
paxdiablo
paxdiablo: ok.... not always easy to tell with all these edits going on ;^)
Toad
But this doesn't solve the question, at least not as I read it. The addresses of the variables should change, not the values?
unwind
Your solution works, but it is not intuitive like MSalters example.
0A0D
Its amazing that such a simple question can raise so many conflicts. Please don't shoot!
RED SOFT ADAIR
+3  A: 

It seems you might be a bit confused about terms.

An object usually has an address. That is the location in memory where the object is located. Some temporary objects don't have addresses, because they don't need to be stored. Such an exception is the temporary "4" object in the expression (2+2)*3

A pointer is an object that stores an address of another object. Hence, for every type, there is a matching pointer. int has int*, std::string has std::string*, etcetera.

Now, you write about "addresses of pointers". They exist. After all, I wrote that a pointer is an object, and thus it has its own address. And you can store that address in another pointer. For instance, you can store the address of and int* in an int* *. But do you really intended that? Or did you mean the "address referenced by a pointer"?

Now, you give height and weight as examples. The standard way to swap them in C++ is simply std::swap(width, height). Note the std::, which is the prefix for C++ standard library functions. std::swap will swap almost everything. ints, floats, wives. (j/k).

You have another swap function, apparently. It accepts two pointers to integers, which means it wants the addresses of two integers. Those are easy to provide, in this case. width is an integer, and &width is its address. That can be stored in the pointer argument int* a. Similarly, you can store the address &height in argument int*b. Putting it together, you get the call swap(&width, &height);

How does this work? The swap(int*a, int*b) function has two pointers, holding the address of two integers in memory. So, what it can do is [1] set aside a copy of the first integer, [2] copy the second integer in the memory where the first integer was, and [3] copy the first integer back in the memory where the second integer was. In code:

 void swap(int *a, int *b)
 {
      int temp = *a; // 1
      *a = *b;       // 2
      *b = temp;     // 3
 }
MSalters
Nice explanation; +1
user9876
+1 wife swap lol
0A0D
A: 

If you want to change address of pointers then you have to pass pointers of those pointers as your parameters:

void swap(int **a, int **b); //as prototype

Those examples are just changes values of pointers.

LostMohican
+3  A: 

If you want to swap the addresses that the pointers are pointing to, not just the values stored at that address, you'll need to pass the pointers by reference (or pointer to pointer).

#include <cassert>
void swap(int*& a, int*& b)
{
    int* c = a;
    a = b;
    b = c;
}

int main()
{
    int a, b;
    int* pa = &a;
    int* pb = &b;

    swap(pa, pb);

    assert(pa == &b);  //pa now stores the address of b
    assert(pb == &a);  //pb now stores the address of a
}

Or you can use the STL swap function and pass it the pointers.

#include <algorithm>

std::swap(pa, pb);

Your question doesn't seem very clear, though.

UncleBens
There is nothing we can do
This is bad practice and missleading code. 1) Unnecessarily complicated. 2) Mixes Pointers and references (Bad practice). I would reject such code from every programmer handling it over to me.
RED SOFT ADAIR
I can't agree (but I'm still new to c++ so I may be wrong). 1) Why is it bad practice? Are we not using passing objects by references whole the time? And pointer is an object so has the right to be treated like one too.2) What is complicated about this I can't really tell.3) I don't see that as mixing pointers and referencess - I just see that as passing object through reference which is quite regular practice of mine.4)Bad Practice? Well in B.S's book The C++ Programming Language are examples of references to pointers and they not marked as bad practice so I think if B.S do it I can do it too
There is nothing we can do
RED SOFT ADAIR
1) It really depends on the circumstances. Naturally storing the dereferenced result of **new** to a reference will be confusing. But this is a different thing here. Passing things by reference is a natural thing to do (e.g makes it clear that NULL pointers are not welcome). 2) Yes, the idea was to show how to do it yourself. And guess what `std::swap` uses - correct, references. 3) Compiler error, which it should as it doesn't make sense. It would also result in a compiler error if you attempted that through a pointer-to-pointer. `swap(`
UncleBens