2

I want to pass a char ** pointer by value. Given the following code:

char **ptr; 

void init(){
    int i;
    ptr = (char**)malloc(2 * sizeof(char*));
    for(i=0;i<2;i++){
         ptr[i]=(char*)malloc(3 * sizeof(char));
         ptr[i] = ..//assign different strings of length 2
    }
}

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

void f(char **ptr1){
    //swap the first and second element
    swap(&ptr1[0],&ptr1[1]);
}

int main{
    init();
    f(ptr);
}

I call the function f with ptr. I want to keep ptr's first values and want to use ptr1 as a copy of it. However, after the swap operation both ptr and ptr1 becomes same. ptr changes. How can I pass it by value?

octopusgrabbus
  • 10,555
  • 15
  • 68
  • 131
thetux4
  • 1,583
  • 10
  • 25
  • 38
  • Why are you assigning to `ptr[i]` twice in the loop? You overwrite the return value of `malloc`. Furthermore, where is `init` being called? – Brett Hale Nov 27 '11 at 14:23
  • Ok I edited. But for each string I also need to take memory. – thetux4 Nov 27 '11 at 14:25
  • What do you mean by "after the swap operation both ptr and ptr1 becomes same"? The `ptr1` variable _disappears immediately after the swap_ when you return from `f`. Also, _of course_ `ptr1` has the same value as `ptr`; that's what you pass into it whwn you call `f`. – hmakholm left over Monica Nov 27 '11 at 14:29
  • When I return from f, ptr1 disappears but also ptr changes. But I just want to keep original values and send a copy of ptr. – thetux4 Nov 27 '11 at 14:32

2 Answers2

2

You want to deep copy (as opposed to shallow copy) your char**. When you call f(ptr), it's like if you were writing

ptr1 = ptr; // by the way, why ptr is global?

and this makes it plain that ptr1 it is pointing to the same area of memory pointed to by ptr. So it's not strange that the swap is affecting ptr, too.

How to fix it? You have to copy each string one by one. You can read this answer on SO for a similar issue (it's C++ but the point is the same).

SUGGESTION If possible, I recommend to

  1. get rid of the global pointer

  2. change init to return the global pointer instead of void, so that it allocates memory and returns a pointer to it

  3. possibly: create a different function which takes in input the values with which you initialize the various strings (Two in your example) of the char**

  4. create a function which frees all the memory allocated (I guess that probably you already have it)

    So that your f() function will init() a new ptr1, will take the values from ptr to initialize the values of the ptr1, and will call the swap on the members (better yet, you can directly initialize without even swapping, just call with the appropriate arguments the function at step 3.

Community
  • 1
  • 1
Francesco
  • 3,200
  • 1
  • 34
  • 46
  • Yeah, thats the reason but I'm trying to find a solution without doing deep copy. – thetux4 Nov 27 '11 at 14:34
  • but in the f() function you have NOT malloc'ed the new memory. You have to replicate what you do in the init() function, namely resrve new memory for each char* pointed to by the char**. Keep the count of the memory allocations: you are only doing them for ptr and not for ptr1. – Francesco Nov 27 '11 at 14:42
0
#include <stdlib.h>
#include <stdio.h>

char ** init()
{
    char **ret;

    ret = malloc(2 * sizeof *ret);
    ret[0] = "world!" ;
    ret[1] = "Hello " ;
    return ret;
}

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

void f(char **ptr1)
{
    //swap the first and second element
    swap(&ptr1[0],&ptr1[1]);
}

int main(void) /* here! */
{
    char **ptr;
    ptr = init();
    f(ptr);
    printf("%s%s\n", ptr[0], ptr[1] );
    return 0;
}
wildplasser
  • 43,142
  • 8
  • 66
  • 109
  • are you sure that the result is what @thetux4 expects? The point was to not modify the first pointer ptr but only the "copy" ptr1, the code that you have shown is modifying ptr. – Francesco Nov 27 '11 at 18:01
  • Well, maybe I understood him wrong. But he could of course create a copy of the two-member array and modify the copy. – wildplasser Nov 27 '11 at 18:08