Thread: Good old 'Swap' function

  1. #1
    Registered User starcatcher's Avatar
    Join Date
    Feb 2008
    Location
    Australia
    Posts
    45

    Question Good old 'Swap' function

    This is what I have is as follows:
    Code:
    void Swap(int *Ptr_A,int *Ptr_B)
    {
    
    int Ptr_Temp; Ptr_Temp=*Ptr_A; *Ptr_A=*Ptr_B; *Ptr_B=Ptr_Temp;
    }
    I would like to expand on this function so that it can be used with parameters which are pointers to any type. That is, I would like to create a function that can swap two objects of any type pointed to by two pointers. In the above example only integers can be swapped. What would be the easiest way of doing that?

  2. #2
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Instead of pointers-to-int, you could use pointers-to-void (and you'd have to malloc space yourself for the temporary); however, you would then need to pass in to your function the size of the data objects, and use memcpy to copy.

  3. #3
    Jack of many languages Dino's Avatar
    Join Date
    Nov 2007
    Location
    Chappell Hill, Texas
    Posts
    2,332
    I've thought about this too. Sure would be handy. Something like:

    Code:
    void Swap(void *Ptr_A, void *Ptr_B)
    {
    void * Ptr_Temp;
    Ptr_Temp= Ptr_A;
    Ptr_A=Ptr_B;
    Ptr_B=Ptr_Temp;
    }
    would be nice.

  4. #4
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Unfortunately, in C, that is hard to do, but something like this:
    Code:
    char *buffer = NULL;
    size_t max_size = 0;
    void Swap(void *Ptr_A,void *Ptr_B, size_t size)
    {
        // Allocate a new buffer when we need a bigger one. Since a big buffer can hold small things, 
        // there's no need to "reduce" the size of the buffer. 
        if (size > max_size)
        {
           free(buffer);
           buffer = malloc(size);
           max_size = size;
        }
        if (buffer == NULL)  // Do some panicing ;
        memcpy(buffer, Ptr_A, size);
        memcpy(PtrA, Ptr_B, size);
        memcpy(Ptr_B, buffer, size);
    }
    You should of course also free the temporary buffer at some point.

    Alternatively, you could use a macro:
    Code:
    #define SWAP(T, A, B)   do { T temp = (A); (A) = (B); (B) = temp; } while(0)
    Use like this:
    Code:
    struct something 
    {
       // stuff here
    };
    
    ...
       struct something a, b;
       ...
       SWAP(struct something, a, b);
    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  5. #5
    Jack of many languages Dino's Avatar
    Join Date
    Nov 2007
    Location
    Chappell Hill, Texas
    Posts
    2,332
    Quote Originally Posted by tabstop View Post
    Instead of pointers-to-int, you could use pointers-to-void (and you'd have to malloc space yourself for the temporary); however, you would then need to pass in to your function the size of the data objects, and use memcpy to copy.
    I think the whole point would be to not have to mem copy the data.

    However, I suspect it might not be a simple as I would like. That's because it's not just the pointer to the area that pointer represents, but also the amount of memory that has been allocated, so free() can work too.

    Todd

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    I think the whole point would be to note have to mem copy the data.
    No, such copying is necessary. Unless one has a swap function with a pointer to a pointer, one cannot just swap pointers (or rather, one can swap pointers, but there would be no net effect).

    The point is to have a swap function that is not restricted to a particular type, like a swap template function in C++.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  7. #7
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Say, you want to sort an array of struct widget, then you will need to swap the widgets, and to do that, you need three memcopies. If you have an array of pointer to struct widget, then you can get away with swapping pointers.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  8. #8
    Jack of many languages Dino's Avatar
    Join Date
    Nov 2007
    Location
    Chappell Hill, Texas
    Posts
    2,332
    Quote Originally Posted by matsp View Post
    Say, you want to sort an array of struct widget, then you will need to swap the widgets, and to do that, you need three memcopies. If you have an array of pointer to struct widget, then you can get away with swapping pointers.

    --
    Mats
    Yes, I think pointers to pointers are the way to go for speed in these cases.

  9. #9
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by Todd Burch View Post
    Yes, I think pointers to pointers are the way to go for speed in these cases.
    Yes, that is much better - but assumes the extra overhead of a second table and/or allocating the objects from the heap instead of just using an array. And sometimes the data isn't "yours" to begin with, so you need to sort whatever was given to you "in place" [say for example you are writing a general purpose sort routine].

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  10. #10
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by Todd Burch View Post
    I've thought about this too. Sure would be handy. Something like:

    Code:
    void Swap(void *Ptr_A, void *Ptr_B)
    {
    void * Ptr_Temp;
    Ptr_Temp= Ptr_A;
    Ptr_A=Ptr_B;
    Ptr_B=Ptr_Temp;
    }
    would be nice.
    That won't work.
    Swapping pointers, however, is easy. In theory, anyway:
    Code:
    void Swap(void** pA, void** pB)
    {
    	void** pTemp = pA;
    	*pA = *pB;
    	*pB = *pTemp;
    }
    Otherwise, you'll have to use mats's code, since C is lacking support for these kind of things. Much easier in C++, though, since a template function would be all that is required.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  11. #11
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Quote Originally Posted by starcatcher View Post
    I would like to expand on this function so that it can be used with parameters which are pointers to any type. That is, I would like to create a function that can swap two objects of any type pointed to by two pointers. In the above example only integers can be swapped. What would be the easiest way of doing that?
    By switching to C++ and using templates.
    Hey, it's the truth - there isn't any easier way!
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  12. #12
    Registered User starcatcher's Avatar
    Join Date
    Feb 2008
    Location
    Australia
    Posts
    45

    Question More questions

    Thank you everyone!
    I had a bit of trouble understanding the swapping pointers method at first,
    but now I think I have an idea how it works. If I have this (in the main
    function of course...):
    Code:
     
    double a=1.23,b=2.34,*ap,*bp;
    ap=&a;
    bp=&b;
    Swap((void **) &ap,(void **) &bp);
     
    void Swap(void **App,void **Bpp)
    
    {
    void **Cpp=App;
    *App = *Bpp;
    *Bpp = *Cpp;
    }
    The thing is though, that afterwards a and b haven't actually been swapped,
    only ap and bp (as expected), and so I can't use the variables a and b until I
    do something like a=*ap,b=*bp in the main function again. Wouldn't it have
    been better just to use matsp's method(s)? Are there cases you can think of
    where just swapping the pointers is all that is required?
    Also, would this work? Would this swap the two elements in the array?
    Code:
    double Array[2];
    Swap((void **) &Array,(void **) &(Array+1))
    That looks REALLY suspect to me. How would you do it otherwise though with the Array?
    What this is all getting at, is as somebody correctly guessed, a general purpose
    bubblesort. How on earth would I be able to use the swapping pointers
    method for something like that?

    I will try the two of Matsp's methods. Which one would you say is quicker?

    Thanks in advance!

  13. #13
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Right, if you want to use the "swap pointer" method, your code would have to look something like this:
    Code:
    double dvalues[10] = { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0 };
    double *array[10] = { &dvalues[0], &dvalues[1], &dvalues[2],  &dvalues[3],  &dvalues[4], &dvalues[5], &dvalues[6], &dvalues[7], &dvalues[8], &dvalues[9] };
    
    Swap(&array[3], &array[4]);
    Swapping pointers only work if you actually use pointers.

    As to which of my methods is faster, it should make very little difference.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  14. #14
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by starcatcher View Post
    How on earth would I be able to use the swapping pointers
    method for something like that?
    Swap pointers only works if you're working with pointers. Otherwise you have to use mats's code. C is very limited in this regard. There's no easy or safe method to swap arguments in C. You need C++ for that.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  15. #15
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by Elysia View Post
    Swap pointers only works if you're working with pointers. Otherwise you have to use mats's code. C is very limited in this regard. There's no easy or safe method to swap arguments in C. You need C++ for that.
    And, how does C++ do it "better"?

    My macro would work just fine - and in compilers with "typeof" it would even be possible to write it as a simpler macro that doesn't take the type. [Although it still doesn't work on arrays].

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 4
    Last Post: 05-13-2011, 08:28 AM
  2. Compiling sample DarkGDK Program
    By Phyxashun in forum Game Programming
    Replies: 6
    Last Post: 01-27-2009, 03:07 AM
  3. Seg Fault in Compare Function
    By tytelizgal in forum C Programming
    Replies: 1
    Last Post: 10-25-2008, 03:06 PM
  4. doubt in c parser coding
    By akshara.sinha in forum C Programming
    Replies: 4
    Last Post: 12-23-2007, 01:49 PM
  5. Problem with Visual C++ Object-Oriented Programming Book.
    By GameGenie in forum C++ Programming
    Replies: 9
    Last Post: 08-29-2005, 11:21 PM