Contents
- Function Definitions
- Function Declarations
- How Functions Are Executed
- Inline Functions
- Recursive Functions
- Variable Numbers of Arguments
Function Definitions
- Functions contain comma-separated parameters (,). If there is no parameters, it will merely contains the word "void".
void Function (int, char); void Function2 (void);
- A static function is a function whose scope is limited to the current source file.
// the scope of this function is limited in this file
static
void
Function2 (void)
{
printf ("Hello world!")
}
- K&R-style
void
Function (a, b) //
int a,b; // K&R-Style
{
printf ("%d %d", a, b);
}
- Parameter has its scope of function scope, and its value can be changed in the function without changing the value of the origin call
void
Change (int a, int b)
{
a = 100;
b = 200;
}
void
main ()
{
int a = 1;
int b = 2;
Change (a, b);
// After calling Change (), the
// value of a & b will not be changed.
printf ("%d, %d", a, b);
}
1, 2
- In function, parameters array will ignore constant in "[]", and the array[] is equivalent to *array
void
ArrayTest (int Array[], int *PtrArray)
{
Array[0] = 99;
PtrArray[1] = 100;
printf ("Array : %d %d\n",
Array[0],
Array[1]
);
printf ("PtrArray : %d %d\n",
PtrArray[0],
PtrArray[1]
);
}
void
main ()
{
int Array[5] = {[0]=5, 6};
ArrayTest (Array, Array);
printf ("Array : %d %d\n",
Array[0],
Array[1]
);
}
Array : 99 100 PtrArray : 99 100 Array : 99 100
- If you want to pass a multiple dimension array to a function, you should do like following codes
void
TripleArray (int a, int b, int c, int Array[a][b][c])
{
printf ("Array[0][1][2] = %d\n", Array[0][1][2]);
}
void
main ()
{
int Array[5][5][5] = {[0][1][2] = 3};
TripleArray (5,5,5,Array);
}
Array[0][1][2] = 3
- Freestanding : Programs execute without OS support, some libraries will unavailable (ex : embeded system, UEFI)
- Hosted : Programs execute with OS support, libraries are available (ex : windows, linux)
- Argc (argument count) Argv (argument vectors) in main (). The first argv will be the name of the program, the others are the remaining
void
main (int argc, char *argv[])
{
printf ("Argument count : %d\n", argc);
printf ("Argument vector 0 : %s\n", argv[0]);
printf ("Argument vector 1 : %s\n", argv[1]);
printf ("Argument vector 2 : %s\n", argv[2]);
}
C:\Project\C_in_nut_shell\CH7>ArgumentsTest Test1 Test2 Argument count : 3 Argument vector 0 : ArgumentsTest Argument vector 1 : Test1 Argument vector 2 : Test2
Function Declarations
- Using the "extern" to link function which is in other file. The declaration can be declare without parameters but it may cause critical error.
- You can declare function prototype at the head of source file without identifiers
- When calling a function, the program will allocates spaces and put the values of the parameters to the space
- If the function type is not void and the end of the function dose not have a return value, the return value is undefined. It will return a value which exists in EAX.
How Functions Are Executed
- When calling a function, the caller will save current RIP and pass parameters. The program will push the RIP and parameters into stack. If the parameters are not pointers, the calling function will copy the parameters into another stack.
int
Yoyoyo (long long a,short *b,char *c,int *d)
{
int Iaa = 0x7f;
}
int main ()
{
long long a = 1;short b = 2;char c = 3;int d = 0;
Yoyoyo (a,&b,&c,&d);
return 0;
}
.text .globl _Yoyoyo .def _Yoyoyo; .scl 2; .type 32; .endef _Yoyoyo: LFB31: .cfi_startproc pushl %ebp .cfi_def_cfa_offset 8 .cfi_offset 5, -8 movl %esp, %ebp .cfi_def_cfa_register 5 subl $24, %esp movl 8(%ebp), %eax movl %eax, -24(%ebp) movl 12(%ebp), %eax movl %eax, -20(%ebp) movl $127, -4(%ebp) leave .cfi_restore 5 .cfi_def_cfa 4, 4 ret .cfi_endproc LFE31: .def ___main; .scl 2; .type 32; .endef .globl _main .def _main; .scl 2; .type 32; .endef _main: LFB32: .cfi_startproc pushl %ebp .cfi_def_cfa_offset 8 .cfi_offset 5, -8 movl %esp, %ebp .cfi_def_cfa_register 5 andl $-16, %esp subl $48, %esp call ___main movl $1, 40(%esp) movl $0, 44(%esp) movw $2, 38(%esp) movb $3, 37(%esp) movl $0, 32(%esp) leal 32(%esp), %eax movl %eax, 16(%esp) leal 37(%esp), %eax movl %eax, 12(%esp) leal 38(%esp), %eax movl %eax, 8(%esp) movl 40(%esp), %eax movl 44(%esp), %edx movl %eax, (%esp) movl %edx, 4(%esp) call _Yoyoyo movl $0, %eax leave .cfi_restore 5 .cfi_def_cfa 4, 4 ret .cfi_endproc LFE32: .ident "GCC: (GNU) 4.8.1"
Inline Functions
- inline : Insert machine codes to the caller. But it is up to the compiler if it is necessary or not
- If a function has a loop, the loop inside will call another function which will cost lots of time saving addresses and push pop parameters. By the time you can use inline.
- If other translation unit calls the inline function but not in the same tanslation unit, it wont be compiled inline.
Recursive Functions
- Direct : Call the function itself.
- Indirect : A function inside calls B function amd B function calls A function
- Recursive functions will push values into stack every call and the programer have to notice that. Or the stack will be exhausted.
Variable Numbers of Arguments
- Like the prototype of printf (). It has (...) to put variadic parameters to it.
int printf(const char * format, ...);
There is a way to retirve the parameters from stack :
void va_start( va_list argptr, lastparam );
- Initial the environment of retrieving arguments
- argptr : Argument pointer
- lastparam : The parameter that the last explicit parameter in the function, for instance, in the printf () is format
type va_arg( va_list argptr, type );
- Retrieving arguments by order
- argptr : Argument pointer
- type : char, int, long.....
void va_end( va_list argptr );
- Must be called if you dont want to take the remaining arguments.
- If you try to get former parameters, you have to call this function and va_start() to reach
int
Yoyoyo (int a, ...)
{
va_list ArgPtr;
va_start (ArgPtr, a);
printf ("%d", va_arg (ArgPtr, double));
va_end (ArgPtr);
}
int main ()
{
int a = 11;
Yoyoyo (a, 1,2,3,4,5,6,7,8,9);
return 0;
}
First Arg : 1
Reference : C in a nutshell

0 意見:
張貼留言