I am a newbie, I just learned C language roughly, I am currently learning C data structures and algorithms, and I want to write about my learning experience and gains in my blog. This is the first one. Talk about formal parameters and actual parameters in C language.
According to my study, the number of formal parameters and actual parameters is equal;
2. Position relationship correspondence;
3. Consistent type;
4. The effect is equal to passing by value (the value of the actual parameter expression, copy a copy, and pass it to the formal parameter) ;
Here's an example: Implementing a swap that swaps two integer variables
#include <stdio.h>
void exchange (int,int);
void exchange (int *one,int *another)
{
int tmp;
tmp = *one;
*one = *another;
*another = tmp;
}
int main()
{
int num1;
int num2;
scanf ("%d",&num1);
scanf ("%d",&num2);
exchange (&num1,&num2);
printf ("The result is: %d,%d\n",num1,num2);
return 0;
}
From a memory perspective:
- num1 is pushed into the stack, and the top pointer of the stack is moved up by 4 bytes;
- num2 is pushed into the stack, and the top pointer of the stack is moved up by 4 bytes;
- Save the on-site information of the main function, and move the stack top pointer up by 8 bytes;
- Push the address information of num2 into the stack, and move the top pointer of the stack up by 4 bytes;
- Push the address information of num1 into the stack, and move the top pointer of the stack up by 4 bytes;
- Pass the address information (first address) of num1 to one;
- Pass the address information (first address) of num2 to another; ! ! ! The space occupied by the value calculated by the actual parameter expression in the stack is the space of the formal parameter variable. The formal parameter and the actual parameter are the relationship of value transfer . The space occupied by the formal parameter is the space that was previously allocated to the actual parameter by the system. !
- tmp is pushed into the stack, and the top pointer of the stack is moved up by 4 bytes;
- Assign the value of the space pointed to by one (the value of num1) to tmp;
- Assign the value of the space pointed to by another (the value of num2) to the space pointed to by one;
- Assign tmp to the space pointed to by another;
- The stack top pointer is moved down by 12 bytes, that is, it points to the main address field information ;
- Continue to execute the main function. . . output. .
One point to mention here: formal parameters are one-way passing, and any modification to the row parameter will not change the original value of the actual parameter expression!
If you continue to explore the essence, you have to mention the content of assembly. The command line compiles the program (cl /FAs exchange.c), generates a file in asm format, and opens the file:
TITLE exchange.c .386P include listing.inc if @Version gt 510 .model FLAT else _TEXT SEGMENT PARA USE32 PUBLIC 'CODE' _TEXT ENDS _DATA SEGMENT DWORD USE32 PUBLIC 'DATA' _DATA ENDS CONST SEGMENT DWORD USE32 PUBLIC 'CONST' CONST ENDS _BSS SEGMENT DWORD USE32 PUBLIC 'BSS' _BSS ENDS _TLS SEGMENT DWORD USE32 PUBLIC 'TLS' _TLS ENDS FLAT GROUP _DATA, CONST, _BSS ASSUME CS: FLAT, DS: FLAT, SS: FLAT endif PUBLIC _exchange _TEXT SEGMENT _one$ = 8 _another$ = 12 _tmp$ = -4 _exchange PROC NEAR ; 6 : { push ebp mov ebp, esp push ecx //ebp value onto the stack (protect main() ebp) //Form an "empty stack" again, which is the empty stack of exchange() ; 7 : int tmp; ; 8 : tmp = *one; mov eax, DWORD PTR _one$[ebp] //mov eax, 4B ebp[4] mov ecx, DWORD PTR [eax] mov DWORD PTR _tmp$[ebp], ecx ; 9 : *one = *another; mov edx, DWORD PTR _one$[ebp] mov eax, DWORD PTR _another$[ebp] mov ecx, DWORD PTR [eax] mov DWORD PTR [edx], ecx ; 10 : *another = tmp; mov edx, DWORD PTR _another$[ebp] mov eax, DWORD PTR _tmp$[ebp] mov DWORD PTR [edx], eax ; 11 : } mov esp, ebp pop ebp //Assign the current value at the top of the stack (main() ebp) to ebp, and esp--4 //Return ebp to the ebp state of the main function ret 0 //mov eip, top of stack //Restore the CPU running order and return to the state when the main function was interrupted _exchange ENDP _TEXT ENDS PUBLIC _main //Main function EXTRN _printf:NEAR EXTRN _scanf:NEAR _DATA SEGMENT //Data area $SG347 DB '%d', 00H ORG $+1 $SG348 DB '%d', 00H ORG $+1 $SG349 DB 0bdH, 0e1H, 0b9H, 0fbH, 0ceH, 0aaH, ':%d,%d', 0aH, 00H _DATA ENDS _TEXT SEGMENT _num1$ = -4 // _num2$ = -8 _main PROC NEAR ; 14 : { push ebp //Push the ebp value into the stack, esp will be -4 mov ebp, esp //Assign the value of esp to ebp; So, esp and ebp point to the same space at this time, forming an empty stack, each function Both have sub esp, 8 //The value of esp is -8, which means that the stack top pointer is raised by 8B, which means that there is an 8B gap between the stack top pointer and the stack bottom pointer, and 8B should be two int spaces; is num1 and num2 //Call the "function" of the main function (the code of the operating system), his ebp is protected (through push and mov), and the bottom space of the original stack is protected ; 15 : int num1; ; 16 : int num2; ; 17 : scanf ("%d",&num1); lea eax, DWORD PTR _num1$[ebp] //-4[ebp] 3[a] = a[3] //lea eax,DWORD PTR -4[ebp] <=> lea eax,DWORD PTR ebp[-4] //eax is stored in the int space starting with ebp-4 //DWORD_PTR is the corresponding to int //The system stack grows to the lower end, which means that the push will be --esp, and the pop will be ++esp //esp: System stack top pointer. ebp: system stack bottom pointer //ebp above the stack bottom pointer, separated by 4B space, is the space of the local variable num1 of the main function //Look at the local variable num2 of the main function, (_num2$ = -8), for the same reason, he is farther away from the pointer at the bottom of the stack, separated by 8B space //! ! ! This means that there is a 4B space between the bottom of the stack and the first local variable (num1)! ! ! //5. This 4B space is the space of num1! ! ! Because the higher the address value in the system stack, the smaller the address value, the lower the address value is! push eax push OFFSET FLAT:$SG347 call _scanf add esp, 8 ; 18 : scanf ("%d",&num2); lea ecx, DWORD PTR _num2 $ [ebp] push ecx push OFFSET FLAT:$SG348 call _scanf add esp, 8 ; 19 : ; 20 : exchange (&num1,&num2); // call the function lea edx, DWORD PTR _num2$[ebp] push edx lea eax, DWORD PTR _num1$[ebp] push eax //Push the first address of num2 and num1 into the stack; call _exchange //The operation of push eip will be executed inside the call instruction! ! ! Protect the value of eip so that it can continue executing the next instruction of the calling function when it returns! //This instruction is the following add esp, 8; then call will execute mov eip, exchange; exchange is the first address constant of the sub-function exchange //CPU will take out the first instruction of the exchange function and start executing, that is, start executing the sub-function exchange //The call here is because push eip is executed; therefore, esp will be -4 again at this time add esp, 8 //esp drops 8 bytes, it just returns to the state before the call ; 21 : printf ("The result is: %d,%d\n",num1,num2); mov ecx, DWORD PTR _num2$[ebp] push ecx mov edx, DWORD PTR _num1$[ebp] push edx push OFFSET FLAT:$SG349 //The essence of the string constant is the first address constant of the string constant call _printf add esp, 12 ; 0000000cH ; 22 : return 0; xor eax, eax ; 23 : } mov esp, ebp pop ebp ret 0 _main ENDP _TEXT ENDS ENDIt is recommended to draw and understand according to the assembly code and the understanding and comments I gave!