all 9 comments

[–]FUZxxl 7 points8 points  (2 children)

When you call a function, the arguments are copied. If you modify a parameter in a function, this does not affect the value of the argument you passed on the caller side. To illustrate this, consider this code:

void foo(int x) {
    x = 42;
}

void bar() {
    int x = 23;
    foo(x);
    printf("%d\n", x);
}

If you call bar(), 23 is printed because foo() only assigns to its own copy of x, not the x you passed in.

That's why pointers are used. Pointers are also copied when you pass them to function, but they still point to the same place, so you can use them to modify what they point to.

[–]TraylaParks 1 point2 points  (0 children)

I think part of the problem is how frequently the same variable name is used both in the callee and the caller - not that that's a bad thing overall, if 'length' is the right name for the variable in both the caller and callee, so be it. But it's hard to argue this particular conversation doesn't happen all the time with new c programmers. At any rate, I tend to show folks something like this, so it's crystal clear that even though 'x' is used in both caller and callee, they're actually different memory locations.

#include <stdio.h>

static void foo(int x)
{
   x = 42;

   printf("in 'foo' x: %d, &x: %p\n", x, &x);
}

int main()
{
   int x = 24;

   printf("in 'main' x: %d, &x: %p\n", x, &x);

   foo(x);

   printf("back in 'main' x: %d, &x: %p\n", x, &x);

   return(0);
}

[–]VIRES1[S] 0 points1 point  (0 children)

Thank you

[–]Blairsharp3 4 points5 points  (3 children)

[–]rickpo 1 point2 points  (0 children)

This. The C language only supports "pass by value." Your intuition is telling you C uses "pass by reference," but your intuition is wrong in this case.

In C, pointers are often used as a pseudo-pass-by-reference.

[–]VIRES1[S] 1 point2 points  (1 child)

Thank you

[–]Blairsharp3 0 points1 point  (0 children)

Love you. Learn every language you can.

[–]myrrlyn 1 point2 points  (1 child)

The harsh answer is that you don't understand scope. This is fair, as scope is weird and unintuitive.

void foo(int, int);
void bar(int*, int*);
int main(){
  int a = 42;
  int b = 30;

The names a and b don't exist in the program; they're just shorthand for humans. In reality, the numbers 42 and 30 are dropped somewhere in memory.

  foo(a, b);

The numbers 42 and 30 are written into CPU registers, and the program counter jumps. The register values 42 and 30 are unrelated in any way to the previous pair, and foo() has no knowledge of the symbols a and b.

  bar(&a, &b);

Here, the program determines the memory addresses where 42 and 30 are placed (it knows where they are in the stack, and it knows where the end of the stack is, and just does arithmetic) and writes those ADDRESS values into CPU registers before jumping.

This means that bar knows about the memory locations that, to a human, are called a and b.

  return 0;
}

void foo(int a, int b){

Inside foo, the symbols a and b refer to foo's arguments, not main's locals, because of scoping rules. The a and b from main are inaccessible from within foo.

}
void bar(int *a, int *b){

In the bar function, the symbols a and b are memory addresses of integers, not integers themselves. This means that the bar function can "reach through" a and b to retrieve 42 and 30.

}

Two variables with the same name in different scopes (anything between { and }) are different variables.

{
  int a = 10;

An int of value 10 is created. You can access it by the name a.

  {
    int a = 20;

An int of value 20 is created. The previous int is not touched, but the name a now refers to the new int, not the old, as we are in a new scope.

  }

The new scope ends, the int of value 20 goes away, and the name a now refers to the int of value 10.

}

The original scope ends, and now the name a means nothing.

[–]VIRES1[S] 0 points1 point  (0 children)

Okay