Is it possible to swap the addresses of two variab

2019-05-25 06:09发布

问题:

I know that it is possible to swap the value of two variables like so

#include <stdio.h>

void swap(int *x, int *y);
int main(){
    int x=5,y=10;
    swap(&x, &y);
    printf("x: %d, y: %d\n", x, y);
    return 0;
}

void swap(int *x, int *y){ 
    int temp;
    temp=*x;
    *x=*y;
    *y=temp;
}

But is it possible to swap the addresses of those two variables? And I don't mean just making a pointer to them and then swapping the values held by the pointers, I mean actually swapping the two, so that after the swap function the address of x is now the address of y before the swap function and vice versa.

I apologise if this is a silly question but I'm curious to see if such a thing is even possible. If this behaviour is not possible, why?

回答1:

No, that's not possible. You don't get to choose the addresses of variables and you can't modify them either.



回答2:

At runtime, you do not have x or y any more. You have two memory addresses with sizeof int bytes reserved at each, which both are assumed to store an integer.

You can swap the contents of these memory areas, and you can have pointer variables with their addresses, and can swap them, as you say. There really isn't any other meaningful way to swap anything here, so answer is "no", because concept of such swapping does not exist.

I suppose, if you had virtual memory pages instead of just integers, then you could swap those, but even that would just be an efficient way to swap memory contents, as far application code is concerned.

If you step outside of high level languages, then you could have self modifying code, where you would change the assembly code of the program to access y instead of x and vice versa. But conceptually this is same as having many pointers embedded into assembly, and changing the pointers. Also, very theoretical way, which requires writable code segment so not even possible in a modern OS without extra tricks.



回答3:

Without passing pointers to pointers, it is not possible. All function calls in C are call by value. Function calls where parameters are of pointer type are often called as "call by reference" (which, by the way, is different from the C++ notion of call by reference) for convenience, but it too is actually call by value. See below example.

void foo(int a, int b) {
    a = 0;
    b = 0;
}

void bar(int* ap, int* bp) {
    ap = NULL;
    bp = NULL;
}

void qux(int* ap, int* bp) {
    *ap = 0;
    *bp = 0;

    ap = NULL;
    bp = NULL;
}

int main() {
    int x = 2;
    int y = 3;
    int* xp = &x;
    int* yp = &y;

    foo(x, y); 
        // x and y don't change here
    bar(xp, yp);  
        // xp and yp don't change here
    qux(xp, yp);
        // xp and yp don't change here, but x and y do
}

It is easy to see how foo() is called by value. Copies of x and y are passed to it (hence call by value). Any changes it makes are to its own copy (which are named a and b within its scope). x and y are unaffected, and will not change in main() after this function returns.

Although somewhat hard to understand for a beginner, bar() too is call by value. Copies of xp and yp are passed to it. Any changes it makes are to its own copy (which are named ap and bp within its scope). xp and yp are unaffected, and will not change in main() after this function returns.

(Notice how the last 3 lines in above paragraph are nearly the same as the previous one. The only difference being that type of x and y are int, while that of xp and yp are int*.)

qux() too is called by value, as it receives copies of xp and yp (known in its scope as ap and bp). However, it can dereference ap and bp, which being copies of xp and yp, point to the same memory location. The memory locations being known in main()'s scope by the names x and y. If qux() makes changes to the value in those memory locations, it will change main()'s "view" of x and y.

The only way to change the values of those pointers through a called function, therefore, is to send addresses of those pointers to the function, which it can then dereference and potentially change. However, your question already rules out that option, so no, this is not possible.



标签: c pointers swap