15

I want to call a function and I want that function to change the contents of a string or array in the program to a constant.

Psuedocode:

some_array = "hello"
print some_array   #prints "hello"
changeArray(some_array)
print some_array  #prints "bingo"

I know I have to pass the pointer to that function. Here's what I wrote,

void changeArray(char *arr){
    arr = "bingo";
}

int main(int argc, const char* argv[]){
    char *blah = "hello";
    printf("Array is %s\n",blah);
    changeArray(blah);
    printf("Array is %s\n",blah);
    return EXIT_SUCCESS;
}

How can I do this?

Brian
  • 14,610
  • 7
  • 35
  • 43
Alex
  • 239
  • 1
  • 3
  • 6

3 Answers3

34

You are passing the pointer to the array by value instead of by reference. It should be:

void changeArray(char **arr){
    *arr = "bingo";
}

int main(int argc, const char* argv[]){
    char *blah = "hello";
    printf("Array is %s\n",blah);
    changeArray(&blah);
    printf("Array is %s\n",blah);
    return EXIT_SUCCESS;
}

You gave the the address of "hello" to changeArray function, but in the function you changed the value passed, not the original pointer. The change I made passes the address of the pointer, and the pointer itself is changed in the function.

Please not char *blah = "hello"; defines a pointer to a constant string, as well as *arr = "bingo";, this is both fine, but if you consider to change the string itself, you will not be able to.

EDIT:

When you pass an argument, even a pointer, to a function, you actually copies it to some place where the function read it from there (usually the stack). You don't pass the argument itself, but a copy of it. When the function modifies it (like in arr = "bingo";) it modifies the copy of the variable, not the original variable. So in order to change the variable itself, we pass the address of the variable to the function (changeArray(&blah); - the & means address of-) and in the function we modify the variable stored in the address we passed (*arr = "bingo"; - the * means the variable in the address arr).

Assuming the original blah pointer is located in the address 0x00000000 and contains the address of "hello" string which is for example 0x00000010. if you pass blah to the function, you copy it to a new variable, arr, which is located in address 0x00000020 for example

Variable    Address     content
-------------------------------
blah       00000000    00000010   (points to hello)
"hello"    00000010    "hello" (this is just an example, so don't be hard on me :) )
arr        00000020    00000010
"bingo"    00000030    "bingo" (and again...)

now if you change the content of arr you change the value in address 0x00000020, but not the value in address 0x000000000, so blah still contains 00000010.

Variable    Address     content
-------------------------------
blah       00000000    00000010   (points to hello)
"hello"    00000010    "hello" (this is just an example, so don't be hard on me :) )
arr        00000020    00000030 (points to "bingo")
"bingo"    00000030    "bingo" (and again...)

Instead what we do is copy the address of blah, which is 0x00000000, to arr and in the function we say - "the content of arr is an address, go to this address and change its content to point to "bingo" string". so now the content in address 0x00000000 (which is blah) is pointing to "bingo".

Variable    Address     content
-------------------------------
blah       00000000    00000030   (points to "bingo")
"hello"    00000010    "hello"    (this is just an example, so don't be hard on me :) )
arr        00000020    00000000   (points to `blah`)
"bingo"    00000030    "bingo"    (and again...)

Hope I didn't confuse you...

MByD
  • 135,866
  • 28
  • 264
  • 277
  • 1
    By all means, *please* rephrase your answer. Arrays are *always* passed by reference in C. If OP wishes to change the array's content, OP should change the elements at each position. With a character array (string), OP should use `strcpy()` or other string function. – André Caron Apr 10 '11 at 12:59
  • @Andre - Thanks for the comment, I changed it to "the pointer to the array", but it is still true that the pointer is passed by value and not by reference. Thanks again. – MByD Apr 10 '11 at 13:01
  • 6
    @AndréCaron: This is a misleading why of looking at it. Arrays are *never* passed into or out of functions at all in C. All functions that look like they take arrays actually take pointers and it is illegal to declare a function returning an array. All parameters, including pointers, are always passed by value into functions in C. C is a "pass by value" only language. – CB Bailey Apr 10 '11 at 13:07
  • Thank you very much. I don't quite understand the difference between *arr and **arr. – Alex Apr 10 '11 at 13:13
  • @Bob - I will try to explain it in my answer. – MByD Apr 10 '11 at 13:23
  • 1
    @André You are incorrect; C only passes by value. An array used as an rvalue is implicitly converted to pointer to its first element. When the rvalue is passed as an argument to a function, the pointer is passed by value. All of this is explicitly and clearly stated in the C standard; I urge you to read it. And if the OP were to use `strcpy` that would result in undefined behavior (and crash with a memory protection violation in most implementations) because `blah` points to a string constant, which cannot be written to. – Jim Balter Apr 12 '11 at 09:11
  • @MByD why don't you need `strcpy`? – cokedude Apr 08 '16 at 07:23
  • @cokedude because `"bingo"` is a string literal, and it is valid outside the context of the function, you can refer to it from anywhere, and so you only need a pointer to it, not a copy of it. – MByD Apr 08 '16 at 22:23
  • What does it actually mean when you drop one * in the function? Is there a pointer hierarchy? – mLstudent33 Jul 06 '20 at 09:41
7

There are no arrays in your code. If you are actually trying to modify what your blah character pointer points to, then you need to pass a pointer to a pointer into the function. However, if you want to do this using arrays then you need to do something like:

void changeArray(char arr[]) {
  // or you can use char *arr, it's the same thing from
  // the C compiler's point of view
  strcpy(arr, "blah");
  // alternatively, you could set each element. i.e. arr[0] = 'b';
}

int main (int argc, char** argv) {
  char blah[100] = "hello"; // this is an array
  printf("Array is %s\n", blah);
  changeArray(blah);   // array decays to pointer
  printf("Array is %s\n", blah);
  return EXIT_SUCCESS;
}
Ferruccio
  • 98,941
  • 38
  • 226
  • 299
  • Thank you, good use of strcpy(). I had a task to do where I wasn't able to use **arr as the parameter in the change function, so this was perfect. – andrewb Apr 06 '13 at 09:54
  • 1
    @Ferruccio why don't you need a `&` with `changeArray(blah)`? – cokedude Apr 08 '16 at 07:25
  • 3
    @cokedude - You can't actually pass arrays as paramenters to functions in C. The arrays will "decay" into a pointer to the first element of the array, so calling `changeArray(blah)` is identical to `changeArray(&blah[0])`. Since the function is declared `void changeArray(char arr[])` which is identical to `changeArray(char* arr)`, the call matches the function signature. – Ferruccio Apr 08 '16 at 13:07
  • Worth to note that the array has 100 places to ensure that there won't be an overflow of the chars to another location in the stack. previously we didn't do that because in C when you assign some string the between quotation mark to a pointer you actually point the pointer to a location the code segment and not the memory stack. – TheLogicGuy Dec 10 '16 at 19:36
  • FWIW, I always write code with an array as this void changeArray(char *arr) but on this IDE I'm working with that does not work. I had to use the notation you used. I'm wondering if its a bug with this compiler/ide set. – netskink Mar 16 '17 at 18:38
0

You need to pass a pointer to array not the array itself.

Another thing: add a control condition to your function. think: what will happen if "bingo" will be bigger than strlen(some_array) ? it will give you an error because in C you must malloc it if you need the array size to be dynamic !

Batman
  • 1,244
  • 2
  • 14
  • 26
  • 1
    this is not correct, he is not copying the string but assigning his pointer to point to the new string. No allocation is needed in this code sample. – MByD Apr 10 '11 at 14:03