Home > Net >  What does pass-by value mean exactly in C?
What does pass-by value mean exactly in C?

Time:05-20

I have probably read hundreds of times the difference between pass-by value and pass-by reference. Pass by reference makes sense because given the address of memory we can directly change what's in there. But pass by value still eludes me.

For example, in here it says that To pass by value means that the argument (a variable, constant or other expression) is evaluated and a copy of its value is then passed to the function..

As far as I know local variables go on stack in the C memory model. Does this mean that if I pass by value a struct with hundred fields each field will be added on top of the stack in order to make a copy?

CodePudding user response:

As far as I know local variables go on stack in the C memory model. Does this mean that if I pass by value a struct with hundred fields each field will be added on top of the stack in order to make a copy?

How arguments are passed can vary. Each computing platform has an application binary interface (ABI) that specifies how arguments are passed, and C implementations typically use the target platform’s ABI, at least for calling functions with external linkage. ABIs for modern general-purpose processors like those in consumer notebooks and desktops typically say the first few arguments of modest sizes are passed in processor registers and other arguments are passed on the stack. (There are embellishments to this, involving structures with diverse or uniform members, alignment issues, SIMD features, and so on.)

If you pass a large structure as an argument, it will be typically passed on the stack, and this may involve a lot of otherwise unnecessary copying of structure members. If you are fortunate, and the compiler can see the definition of the function while it is compiling the call to the function, it might optimize this part of the program by “inlining” the function. This means that, instead of actually calling the function, it builds the code of the called function into the calling function. This, and the subsequent optimization on the integrated code, might eliminate some or all of the copying of the structure, depending on circumstances.

Nonetheless, it should generally be avoided. If a function needs to read data from a large structure, it is preferable to declare a parameter that is a pointer to a const-qualified type of that structure.

(There is a related issue with returning a value: A function can also return a structure. The way this is commonly implemented, and specified in ABIs, is that there is an extra parameter passed to the function in addition to those declared in the source code. When a function is calling a function that returns a structure, the calling function sets aside space for the structure and passes the address of that space in the extra parameter. Then the called function stores the return value in that space.)

CodePudding user response:

It means that values passed to functions as parameter have their values copied (new memory is created to store them), and the function's parameter is not a alias or reference to memory that holds the thing the caller provided.

For example, consider this pseudo code.

func f(x):
   x  = 1

y = 1
f(y)
print(y)

In languages with pass-by-reference semantics 2 is printed - x is a reference/alias to the memory that holds the data of variable, y. f changes the value of the thing the caller provided, for the caller of the function.

With pass-by-value semantics 1 is printed, because a copy of the value of y is provided as the parameter to the function. The new memory for this new data is typically placed on a stack, and destroyed/released/recycled when f returns.

In C, specifically:

void f(int x) {
   x  = 1;
}
...
int y = 1;
f(y);            
printf("%d", y);  // "1"

Note that C is pass-by-value even though it has pointers. All this means is that a copies of memory addresses are passed as the values to a functions, for functions with pointer arguments. This doesn't prevent you from referencing memory created outside of the scope of a C function, but it does mean that the pointer can have its addressed value modified independently within the scope of the function.

void f(int* x) {
   printf("X1 %p", x);   // The memory location of the value of y
   printf("X val %d", *x);  // The value of y
   x  = 1;            // The next memory address after the value of y ?!!!!
   printf("X2 %d", x);  // Address   sizeof(int)
   // Look. We modified a copy of a memory address.
   // y_ptr is NOT motified - call-by-vlaue means a copy was provided.
}
...
int y = 1;
int* y_ptr = &y;
printf("Y1 %p", y_ptr);   // Memory location of the data for y.
f(&y);
printf("Y2 %p", y_ptr);   // Same as Y1
printf("Y  %d", y);       // 1, if we didn't crash yet
  •  Tags:  
  • c
  • Related