Parameter transfer mechanism in C language

  • 2020-05-17 06:06:01
  • OfStack

Parameter passing in C

In this paper, we try to discuss the relationship of real participation formal parameters in C, that is, the problem of parameter passing.

Parameter passing for the C language

Value passed

First look at the following code:


#include <stdio.h>
 
int main(){
  int n = 1;
  printf(" The arguments n Value: %d, Address: %#x\n", n, &n);
  void change(int i);// Function declaration 
  change(n);
  printf(" Arguments after the function is called n Value: %d, Address: %#x\n", n, &n);
  return 0;
}
 
void change(int i){
  printf(" parameter i Value: %d , address: %#x\n",i,&i);
  i++;
  printf(" Form parameters after operation are added i Value: %d , address: %#x\n",i,&i);
}
 

The compiled results are as follows:


 The arguments n Value: 1, Address: 0x5fcb0c
 parameter i Value: 1 , address: 0x5fcae0
 Form parameters after operation are added i Value: 2 , address: 0x5fcae0
 Arguments after the function is called n Value: 1, Address: 0x5fcb0c
 

As you can see, when the function change is called, a separate space is created in memory for the formal parameter i, and the value of the argument n is copied to the formal parameter i. Any operation on formal parameters does not affect the argument n in the main function. This method of parameter passing is the typical value passing.

The parameter type in the above example is int type. In fact, parameters of the basic types of plastic (int, short, long, long long), floating point (float, double, long double), and character type (char) are all value passed.

Pointer parameter

In the following example, the parameter type of the function is 1 pointer:


#include <stdio.h>
 
void change(int * i){
  printf(" parameter i Value: %#x , address: %#x\n",i,&i);
  (*i)++;// The pointer modifies the value of the space it refers to 
  i++;// Let's put the pointer down 1 Block memory space 
  printf(" Form parameters after operation are added i Value: %#x , address: %#x\n",i,&i);
}
 
int main(){
  int n = 1;
  int * p = &n;
  printf("n Value: %d, Address: %#x\n", n, &n);
  printf(" The arguments p Value: %#x, Address: %#x\n", p, &p);
  change(p);
  printf(" Arguments after the function is called p Value: %#x, Address: %#x\n", p, &p);
  printf(" After the function is called n Value: %d, Address: %#x\n", n, &n);
  return 0;
}
 

The compiled results are as follows:


n Value: 1, Address: 0x5fcb0c
 The arguments p Value: 0x5fcb0c, Address: 0x5fcb00
 parameter i Value: 0x5fcb0c , address: 0x5fcae0
 Form parameters after operation are added i Value: 0x5fcb10 , address: 0x5fcae0
 Arguments after the function is called p Value: 0x5fcb0c, Address: 0x5fcb00
 After the function is called n Value: 2, Address: 0x5fcb0c
 

A pointer is a special type in the C language, which itself takes up a fixed amount of memory, while the stored value is a certain memory address. In the above example, the parameter of the function change is a pointer to the variable int, and the argument p is a pointer to the variable n. When the function change is called, the pointer parameter i will also get a block of memory space, and its value is copied from the argument p, which is the address of the variable n in the main call function. For pointer types, 1 is generally less concerned with itself and more concerned with the value it points to, so within the change function, a pointer is used to manipulate what the pointer points to (the variable n in the main call function). In this way, the effect of manipulating the data in the tunable function is realized.

Although the pointer parameter transfer can achieve the effect of making the operation in the called function act on the data in the main function, from the point of view of arguments and formal parameters, this parameter transfer does not have any essential difference from the 1-like transfer method, but is also the value transfer method.

When the parameter is passed by value, the parameter and argument are stored in their respective memory space, independent of each other. The only relation between them is that the parameter value will be used when the parameter is initialized.

Array parameter

In C, the array name is treated as a pointer constant to the first element of the array, so how is the array passed as a parameter? In fact, when the function parameter is an array type, the array name no longer represents the array, but is resolved by the compiler into a pointer. As you can see from the following example, the parameter of array type only looks like an array in the function signature, but in the function body, it has been completely reduced to a pointer.


#include <stdio.h>
 
void arrArg(int arr[]){
  printf(" parameter arr Value: %#x , address: %#x\n", arr, &arr);
  printf("sizeof(arr) : %d, sizeof(int *) : %d\n",sizeof(arr), sizeof(int *));
  printf("sizeof(arr[0]) : %d . sizeof(int) : %d\n", sizeof(arr[0]), sizeof(int));
  printf("*arr : %d . arr[0] : %d\n", *arr, arr[0]);
  printf("*(arr+1) : %d . arr[1] : %d\n", *(arr+1), arr[1]);
  printf("arr+1:%#x . &arr[1] : %#x\n",arr+1, &arr[1]);
  arr++;
  printf(" Form parameters after operation are added arr Value: %#x , address: %#x\n",arr, &arr);
  printf(" Since the increment operation ,*arr : %d, arr[0] : %d\n",*arr, arr[0]);
}
 
int main(){
  int a[] = {1,2,3};
  printf(" The arguments a Value: %#x , address: %#x\n",a,&a);
  printf("sizeof(a) : %d . sizeof(a[0]) : %d\n",sizeof(a),sizeof(a[0]));
  arrArg(a);
  return 0;
}
 

The compiled results are as follows:


 The arguments a Value: 0x5fcb00 , address: 0x5fcb00
sizeof(a) : 12 . sizeof(a[0]) : 4
 parameter arr Value: 0x5fcb00 , address: 0x5fcae0
sizeof(arr) : 8, sizeof(int *) : 8
sizeof(arr[0]) : 4 . sizeof(int) : 4
*arr : 1 . arr[0] : 1
*(arr+1) : 2 . arr[1] : 2
arr+1:0x5fcb04 . &arr[1] : 0x5fcb04
 Form parameters after operation are added arr Value: 0x5fcb04 , address: 0x5fcae0
 Since the increment operation ,*arr : 2, arr[0] : 2
 

It can be seen that, although the parameter arr is declared as an int array, inside the function, arr no longer has the property of an array, but of a pointer to int:

The size of arr is the size of the pointer (8), not the size of the array (the size of the array is the sum of the sizes of all the elements, in the example above: 4×3=12).
arr can be modified, but array names cannot be modified
The memory address of arr is different from that of a but has the same value (both are the address of the first element of the array). Therefore, when the function is called, the actual value passed is the address of the first element of the array, and a pointer to the first element of the real parameter set is initialized from this address as the parameter parameter. Since the actual parameter is a pointer, this is also a case of value passing. At the same time, changes to the "array" inside the function will be acted on externally, just like pointer parameter effect 1.

From this we can see that there is no difference between an array as an argument and a pointer as an argument, because the compiler automatically converts the array name in the parameter to a pointer. Therefore, the signature of the two functions in the following code is equivalent:


void func(int arr[]){
 
}
void func(int * p){
 
}
 

In fact, if we define them at the same time, the compiler will report an "redefinition" error and fail to compile.

In addition it is important to note that although we would declare parameter into one array, but the compiler looks like it is just a pointer, so information of the parameters about the length of the array will automatically be ignored, in the actual call real parameter set with parameter to specify the length of the array length without any relationship, but also fail sizeof within the function (arr)/sizeof (arr [0]) for the length of the array.


// parameter arr Specified length of 5 Meaningless, will be ignored by the compiler, not to prevent misunderstanding recommendations not to write 
void arrArg(int arr[5]){
 // sizeof ( arr ) is the size of the pointer type rather than the array size, therefore len Not array length  
 int len = sizeof(arr)/ sizeof(arr[0]);
}
 

Custom type parameters

The "combined" type of array is parsed as a pointer when passed as a parameter, so is it true when structs (struct), communities (union), and enumerated types are passed as parameters?

Enumeration types are essentially int, so when the parameter is declared as an enumeration type, it will appear to the compiler as int type. The compiler will report an "redefinition" error if the two function signatures in the following code are equivalent:


enum week{ Mon, Tues, Wed, Thurs, Fri, Sat, Sun };
 
void func(enum weekday){}
 
void func(int i){}
 

The following is an example of a structure and a community as parameters:


#include <stdio.h>
 
struct Date{
  int year;
  int month;
  int day;
};
 
void changeStruct(struct Datedate){
  printf(" parameter date Address: %#x\n", &date);
  date.year ++;
  date.month = 12;
  date.day = 31;
  printf(" parameter date The value of the :%d-%d-%d\n",date.year,date.month,date.day);
}
 
union Data{
  int i;
  float f;
  double d;
};
 
void changeUnion(unionDatadata ){
  printf(" parameter data Address: %#x\n", &data);
  printf(" parameter data The value of the ,d.i:%d, d.f:%f, d.d:%f\n",data.i,data.f,data.d);
  data.d = 2017.4;
  printf(" After the function is called, the parameter is formed data The value of the ,d.i:%d, d.f:%f, d.d:%f\n",data.i,data.f,data.d);
}
 
int main(){
  printf(" Example of structure parameter transfer: \n");
  struct Datedate = {2017,4,2};
  printf(" The arguments date Address: %#x\n", &date);
  printf(" The arguments date The value of the :%d-%d-%d\n",date.year,date.month,date.day);
  changeStruct(date);
  printf(" After the function is called, the argument date The value of the :%d-%d-%d\n",date.year,date.month,date.day);
 
  printf(" Example of Shared parameter passing: \n");
  unionDatadata={.i=2017};
  printf(" The arguments data Address: %#x\n", &data);
  printf(" The arguments data The value of the ,d.i:%d, d.f:%f, d.d:%f\n",data.i,data.f,data.d);
  changeUnion(data);
  printf(" After the function is called, the argument data The value of the ,d.i:%d, d.f:%f, d.d:%f\n",data.i,data.f,data.d);
 
  return 0;
}
 

Run after compiling, and the output is as follows:


 The arguments n Value: 1, Address: 0x5fcb0c
 parameter i Value: 1 , address: 0x5fcae0
 Form parameters after operation are added i Value: 2 , address: 0x5fcae0
 Arguments after the function is called n Value: 1, Address: 0x5fcb0c
 
0

We found that custom types in C, when passed as arguments, are passed by value, as are basic types 1.

summary

In the C language, when the parameter types are character, integer, floating point, and enumeration, struct (struct) and community (union), they are all regular value pass-through. And pointer as a kind of special type, its value is an address that points to the base type can be any other types (including void) can even point to function, so the pointer though essentially belongs to the value passed as a parameter, but because of transfer is one address, can let be callback function through direct effect to the operation of the pointer refers to the content to the external data, belongs to the special values in the parameter passed. While you can declare parameters as arrays, the actual parameters are Pointers, so arrays are passed as special values.

We looked at the various data types in C in turn and found that: C only passes values!


Related articles: