Thread: Swap Integers

  1. #1
    Registered User
    Join Date
    Aug 2003
    Posts
    21

    Swap Integers

    I have to write a function that will swap the value of two integers around. The definition for the function is swapInts(int *firstInt, int *secondInt);

    As it's address' that's being passed in I thought the following would do it:

    Code:
    void swapInts(int *firstInt, int *secondInt)
    {
    	int *tempInt = firstInt;
    	firstInt = secondInt;
    	secondInt = tempInt;
    }
    In fact, I still think that the above should work but I can't figure out why it doesn't. The lines that are calling the above look like this:

    Code:
    int firstInt = 1;
    int secondInt = 2;
    
    swapInts(firstInt, secondInt);
    
    std::cout << "firstInt: " << firstInt << " secondInt: " << secondInt << "\n";
    If I test the value of firstInt and secondInt at the end of the swapInts function they are swapped but when they're output back in the main program they aren't anymore. Why is this?

    The only way I could get it to work is to use the actual values of the ints like this:

    Code:
    void swapInts(int *firstInt, int *secondInt)
    {
    	int tempInt = *firstInt;
    	*firstInt = *secondInt;
    	*secondInt = tempInt;
    }
    But this seems a bit silly. Surely I could just change the address' that the variables are pointing to?

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > swapInts(firstInt, secondInt);
    This shouldn't even compile, given your function definition.

    > Surely I could just change the address' that the variables are pointing to?
    You can't change where a variable exists.

    You pass a pointer to the two ints, then swap the data by dereferencing those pointers.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Aug 2003
    Posts
    21
    Quote Originally Posted by Salem View Post
    > swapInts(firstInt, secondInt);
    This shouldn't even compile, given your function definition.
    You're right. It was swapInts(&firstInt, &secondInt);

    Quote Originally Posted by Salem View Post
    > Surely I could just change the address' that the variables are pointing to?
    You can't change where a variable exists.

    You pass a pointer to the two ints, then swap the data by dereferencing those pointers.
    If that's the case then why does it work in the function? If I do...

    int firstInt = 1;
    int secondInt = 2;

    ...and say the address' for these variables are (for argument's sake) 0x22CCE4 and 0x22CCE0 respectively then when I set the address of secondInt to 0x22CCE4 it's value will be 1. By the same token, if I set the address of firstInt to 0X22CCE0 it's value should be 2. That's the because the values stored at those address' are 1 and 2 respectively, right?

    Or am I missing something completely?

  4. #4
    The larch
    Join Date
    May 2006
    Posts
    3,573
    The more C++ way in this situation is to use references.

    Code:
    void swap(int& a, int& b)
    {
        int temp = a;
        a = b;
        b = temp;
    }
    
    int main()
    {
        int first = 1, second = 2;
        swap(first, second);
    }
    A reference (declared with the & symbol) means that the variable is not a copy of the value passed as an argument, but an alias or another name for the original variable in the calling code.

    As for your question, you can't change the address of a variable. You can change where a pointer is pointing to but in this case you are not swapping pointers but the contents of what the two pointers are pointing to. (In main you don't declare pointers but ints and try to change their content.)

  5. #5
    Registered User
    Join Date
    Aug 2003
    Posts
    21
    Quote Originally Posted by anon View Post
    The more C++ way in this situation is to use references.
    I think that's a little subjective. Even so, I AM using references. See: swapInts(&firstInt, &secondInt);

    Quote Originally Posted by anon View Post
    A reference (declared with the & symbol) means that the variable is not a copy of the value passed as an argument, but an alias or another name for the original variable in the calling code.
    A thought a reference was literally the address of the variable? So it essentially gets you a pointer to the address that the value is stored in.

    Quote Originally Posted by anon View Post
    As for your question, you can't change the address of a variable.
    Again, if I can't then why does it work in the function.

    Quote Originally Posted by anon View Post
    You can change where a pointer is pointing to but in this case you are not swapping pointers but the contents of what the two pointers are pointing to. (In main you don't declare pointers but ints and try to change their content.)
    Well, if I use pointers I still get the same result. I changed int firstInt = 10 to int *firstInt = new int(10) and int secondInt = 20 to int *secondInt = new int(20) and again, they were swapped in the function but when I output their values they aren't.

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    I think that's a little subjective.
    A little subjective, yes, but mostly objective since that is the way the standard library does it.

    Even so, I AM using references. See: swapInts(&firstInt, &secondInt);
    No, that is more like using pointers and addresses than references.

    A thought a reference was literally the address of the variable? So it essentially gets you a pointer to the address that the value is stored in.
    In C++, a reference is an alias, a pointer is a variable that holds an address.

    Surely I could just change the address' that the variables are pointing to?
    The pointer arguments in your swap function are local variables.
    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
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Quote Originally Posted by redneon View Post
    I think that's a little subjective. Even so, I AM using references. See: swapInts(&firstInt, &secondInt);
    It's more like intersubjective (Its easier to make mistakes with pointers...)
    And you are not using references, but the address-of operator. (Yes in C++ many operators have different meanings in different contexts.)

    A thought a reference was literally the address of the variable? So it essentially gets you a pointer to the address that the value is stored in.
    Not quite. The syntax how you use a reference is identical to how you use a variable (not a pointer). You can't have a NULL-reference and you can't change what a reference is referencing (make int& c first a reference of int a and then change it into a reference of int b).

    Again, if I can't then why does it work in the function.
    You have to make yourself clear whats the difference between a pointer and what it points to. The function works because you pass it the addresses of two int variables (which become local copies of the pointers you pass) and you swap what resides at these addresses.
    The pointers themselves, however, are local to the function and therefore have no effect to the calling code.

    Code:
    swap(int* a, int* b) //a and b are local to the function
    {
        int* temp = a;
        a = b;
        b = temp;
        //no effect because a and b go out of scope here
    }
    Hence, if you want to swap whole arrays (pointers), you'll need to take it one step further and pass a pointer to the pointer that points to the array (or a reference of the pointer to the array).
    Last edited by anon; 04-28-2007 at 08:57 AM.

  8. #8
    Registered User
    Join Date
    Aug 2003
    Posts
    21
    Ok. I'm a little confused about pointers then. I understand references now but take the following code:

    Code:
    void inc(int *val)
    {
        *val++;
    }
    
    int main()
    {
        int a = 10;
        inc(&a);
    
        std::cout << "a: " << a;
    }
    The function inc takes a pointer to an address as an argument, right? So when I pass it the address of the variable a val should equal the address of a. So, when I do *val++ I am then incrementing the value stored in the address of a, correct? If this is the case, any other pointers that point to that address should then contain the new value, surely?

    So in the above, int a = 10. Then it's address is passed into the function inc. The value that's stored at that address is then incremented by 1. So back in main, the value of a should now be 11, but it isn't.

    I'm obviously not understanding something about pointers. I understand that if I used a reference the variable a would get incremented because effectively the reference IS the variable a. It's just the pointers that's blowing my mind =o)
    Last edited by redneon; 04-28-2007 at 09:11 AM.

  9. #9
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Quote Originally Posted by redneon View Post
    The function int takes a pointer to an address as an argument, right? So when I pass it the address of the variable a val should equal the address of a.
    No and no. The function takes a pointer to an int, which is an address. And in the function you are incrementing the pointer, not what it points to.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  10. #10
    The larch
    Join Date
    May 2006
    Posts
    3,573
    This was recently discussed in another thread. The function is equivalent to:
    Code:
    void inc(int *val)
    {
        //*val++; // ==> *(val++);
        *val; //has no effect
         val++;  //possibly undefined result? For sure undefined to dereference now.
    }
    
    int main()
    {
        int a = 10;
        inc(&a);
    
        std::cout << "a: " << a;
    }
    Because of precedence of operators, it should look like this:
    Code:
    void inc(int *val)
    {
        (*val)++;
    }
    Or again, you might see how using a reference leaves less room for mistakes and misunderstanding:
    Code:
    void inc(int& val)
    {
        val++;
    }
    Last edited by anon; 04-28-2007 at 09:23 AM.

  11. #11
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Or
    Code:
    void inc(int *val)
    {
        ++*val;
    }
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  12. #12
    Registered User
    Join Date
    Aug 2003
    Posts
    21
    Quote Originally Posted by Dave_Sinkula View Post
    No and no. The function takes a pointer to an int, which is an address. And in the function you are incrementing the pointer, not what it points to.
    Ah, I think I understand but I just want someone to confirm it.

    If in my main function I do this:

    Code:
        int a = 100;
        int *b = &a;
    
        *b += 50;
    Then both a and b's values will be 150 because they both point to the same address, correct?

    Now, if I did this:

    Code:
    void inc(int *val)
    {
        *val += 50;
    }
    
    int main()
    {
        int a = 100;
    }
    The argument int *val in the function inc() is a pointer to a new int with a different address. So, although I'm passing a pointer to an int as an argument the pointer for both wont point to the same address, right?

  13. #13
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Ah, I think I understand but I just want someone to confirm it.

    If in my main function I do this:

    Code:

    int a = 100;
    int *b = &a;

    *b += 50;

    Then both a and b's values will be 150 because they both point to the same address, correct?
    "a" is a variable that initially has the value of 100.
    "b" is a pointer to "a" (b's value is some memory address, and the value at that memory address is that of "a": 100).
    After the increment, where you dereference "b", i.e use it to "go" to the memory location which has 100, the memory (variable "a") that "b" points to will have the value 150.
    Now "*b == 150" and "*b == a" but "b == &a" - b itself will still have the same value as before: the address of a that didn't change.

  14. #14
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    The argument int *val in the function inc() is a pointer to a new int with a different address.
    It is a pointer to the int variable whose address was passed to it. You are not actually using inc() in your second code example. If you call inc(&a), then val in inc() does point to a, for the duration of that function call.
    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

  15. #15
    Registered User
    Join Date
    Aug 2003
    Posts
    21
    Quote Originally Posted by anon View Post
    "a" is a variable that initially has the value of 100.
    "b" is a pointer to "a" (b's value is some memory address, and the value at that memory address is that of "a": 100).
    After the increment, where you dereference "b", i.e use it to "go" to the memory location which has 100, the memory (variable "a") that "b" points to will have the value 150.
    Now "*b == 150" and "*b == a" but "b == &a" - b itself will still have the same value as before: the address of a that didn't change.
    Yeah, I get that. b doesn't actually contain a value. It contains the address of a. So when I increment the value stored in the memory address that b point to I am incrementing the value of a by proxy.

    That's why I'm confused about the function. If it works in main then I would have thought that doing...

    Code:
    void inc(int *b)
    {
        *b += 50;
    }
    
    int main()
    {
        int a = 100;
    
        inc(&a);
    
        return 0;
    }
    ...would work.

    EDIT: Fixed stupid mistakes. Evidently it does work =o)
    Last edited by redneon; 04-28-2007 at 09:42 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Link List math
    By t014y in forum C Programming
    Replies: 17
    Last Post: 02-20-2009, 06:55 PM
  2. Assignment HELP!!
    By cprogrammer22 in forum C Programming
    Replies: 35
    Last Post: 01-24-2009, 02:24 PM
  3. Integers into array.
    By livestrng in forum C Programming
    Replies: 10
    Last Post: 10-29-2008, 11:35 PM
  4. using swap to make assignment operator exception safe
    By George2 in forum C++ Programming
    Replies: 9
    Last Post: 01-10-2008, 06:32 AM
  5. Replies: 6
    Last Post: 08-04-2003, 10:57 AM