10

How to change value of variable passed as argument in C? I tried this:

void foo(char *foo, int baa){
    if(baa) {
        foo = "ab";
    } else {
        foo = "cb";
    }
}

and call:

char *x = "baa";
foo(x, 1);
printf("%s\n", x);

but it prints baa why? thanks in advance.

Robb1
  • 4,587
  • 6
  • 31
  • 60
Jack
  • 16,276
  • 55
  • 159
  • 284
  • If(baa)? Its not a bool value, is this legal in c? – Induster Feb 27 '12 at 03:33
  • 1
    @Induster There are no Boolean types in C. All Boolean logic is done with ints. – Phonon Feb 27 '12 at 03:35
  • 1
    @Phonon, wrong. Since C99 the language has `_Bool` as a primitive type and `bool` in "stdbool.h". – Jens Gustedt Feb 27 '12 at 07:28
  • 1
    All the same, boolean comparisons in C still simply check against zero-equivalence; while there are a number of implementations of _Bool it's typically just an integer word with restricted zero-or-one value. – Michael Macha Dec 20 '20 at 16:56

4 Answers4

18

You're wanting to change where a char* points, therefore you're going to need to accept an argument in foo() with one more level of indirection; a char** (pointer to a char pointer).

Therefore foo() would be rewritten as:

void foo(char **foo /* changed */, int baa)
{
   if(baa) 
   {
      *foo = "ab"; /* changed */
   }
   else 
   {
      *foo = "cb"; /* changed */
   }
}

Now when calling foo(), you'll pass a pointer to x using the address-of operator (&):

foo(&x, 1);

The reason why your incorrect snippet prints baa is because you're simply assigning a new value to the local variable char *foo, which is unrelated to x. Therefore the value of x is never modified.

AusCBloke
  • 18,014
  • 6
  • 40
  • 44
7

There are multiple issues:

void foo(char *foo, int baa)
{
    if (baa) 
        foo = "ab";
    else 
        foo = "cb";
}

This code changes the local pointer, but does nothing with it. To copy strings around, you need to use strcpy() to keep the interface the same:

void foo(char *foo, int baa)
{
    if (baa) 
        strcpy(foo, "ab");
    else 
        strcpy(foo, "cb");
}

However, before doing that, you'd need to ensure that foo in the function points at modifiable memory. The calling code needs to be modified to ensure that:

char x[] = "baa";
foo(x, 1);
printf("%s\n", x);

Alternatively, you can keep x as a pointer and revise the function interface:

void foo(char **foo, int baa)
{
    if (baa) 
        *foo = "ab";
    else 
        *foo = "cb";
}

and the calling sequence:

char *x = "baa";
foo(&x, 1);
printf("%s\n", x);

Both mechanisms work, but do so in their different ways. There are different sets of issues with each. There isn't a single 'this is better than that' decision; which is better depends on circumstances outside the scope of the code fragments shown.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
6

You question is titled in a generic way. You've already got answers for your specific problem. I'm going to add couple of illustrative examples for int and double types.

#include <stdio.h>

void incrementInt(int* in, int inc)
{
   *in += inc;
}

void incrementDouble(double* in, double inc)
{
   *in += inc;
}

int main()
{
   int i = 10;
   double d = 10.2;

   printf("i: %d, d: %lf\n", i, d);

   incrementInt(&i, 20);
   incrementDouble(&d, 9.7);

   printf("i: %d, d: %lf\n", i, d);
}

Output:

i: 10, d: 10.200000
i: 30, d: 19.900000
R Sahu
  • 204,454
  • 14
  • 159
  • 270
0

in function foo, you are changing argument foo only locally. when function foo ends, argument x is still x. You didn't change it in foo. you only copied it and called foo.

also, look at @Greg Hewgill comment.

fazo
  • 1,807
  • 12
  • 15