-3

C program below

void test_func(int a, int b, int *c) {
    a ^= 5;
    *c = a + b;
    b <<= 4;
}

int main() {
    int a = 3, b = 0x011, c = 0;
    test_func(a, b, &c);
    a = (b > c) ? b : c;
    printf ("%d %d %d",a,b,c);
}

The compiler outputs a = 23,b=17 and c = 23 which is not what i expected. I brainstormed step by step in this way :

Main function
Function call is made where a = 3 , b = 17(in int), c=0
and values are passed to the test_func 
Functions runs:
a = 3 ^ 5 = 0110 or 6 ; 
c = 17+ 6 = 10100 or 23;
b = 17x2^4 = 272 ; (by the formula of bitwise left shift operator)
Return to the main function
b is definitely greater than c so a returns 272 ;

Therefore I expected the result 272,272 and 23 . However the compiler shows 23,17,23. It took me quite a while to realize that b<<=4 never changed the value of b in main function. Please explain why is that so , why didn't the value of b change in main function if values of a and c did?

sg7
  • 6,108
  • 2
  • 32
  • 40
holahola
  • 59
  • 3
  • 9
  • 3
    I'll give you a hint: you're doing the right thing with `c` that you aren't doing with `b`. –  Mar 19 '18 at 18:16
  • 1
    C passes parameters by *value*, unless you specify otherwise. – Fred Larson Mar 19 '18 at 18:16
  • 1
    Function parameter variables are distinct entities from the arguments the function is called with. The parameters are a *copy* of (a potential conversion of) the arguments. (Reference semantics can be implemented by using pointers.) – Kerrek SB Mar 19 '18 at 18:17
  • 2
    Try to name the parameters `x`, `y`, and `z`, and see if that changes the expectations. – Bo Persson Mar 19 '18 at 18:18

1 Answers1

4

In C, all parameters are pass by value. That means that changing the value of a function parameter is not reflected in the calling function.

You can however emulate passing by reference by passing the address of a variable to a function, as you did with c. When you then dereference the pointer variable in the function, you're changing what c in test_func points to, i.e. c in main.

This is why b doesn't change in main. For the same reason, a also doesn't change. a does however change on the following line when it is assigned to.

It's also important to note that a, b, and c in main are not the same as a, b, and c in test_func. You could change the names in either one and it will work the same way.

In order for a and b to change, you need to pass their addresses, just like you did with c. So change the type of the parameters of your function (and dereference to get the values):

void test_func(int *a, int *b, int *c) {
  *a ^= 5;
  *c = *a + *b;
  *b <<= 4;
}

Then call it like this, passing in the addresses of a and b:

test_func(&a, &b, &c);
dbush
  • 205,898
  • 23
  • 218
  • 273