A function is a block of code that performs a specific task.

Dividing a complex problem into smaller chunks makes our program easy to understand and reuse.

  • C 语言的程序由 函数 组成, 函数是 C 语言程序的基本单位.
  • C 语言程序可以只包含一个 main 函数; 但如果要实现的功能比较复杂, 从程序的 模块化实现 / 代码重用性 等因素考虑, 应当要定义并实现一些自定义函数.
  • 函数分类:
    • 函数定义角度: 标准库函数 & 自定义函数;
    • 函数过程角度: 有返回值函数 & 无返回值函数
    • 主调函数&被调函数角度: 无参函数 & 有参函数
  • C 语言中, 函数的定义&实现位置可以比较灵活, 但函数 不能嵌套定义(即: 一个函数的定义不能位于另一函数的函数体中)

0.1.1 标准库函数 Standard library functions

  • The standard library functions are built-in functions in C programming.
  • These functions are defined in header files.(printf() in stdio.h; sqrt() in math.h)

0.1.2 用户自定义函数 User-defined functions

  • Note, function names are identifiers and should be unique.

0.2.1 无参无返回值

0.2.2 无参有返回值

0.3.1 有参无返回值

0.3.2 有参有返回值

1.1 函数原型 Function prototype

  • A function prototype is simply the declaration of a function that specifies function's name, parameters and return type. It doesn't contain function body.
  • A function prototype gives information to the compiler that the function may later be used in the program.
  • The function prototype is not needed if the user-defined function is defined before the main() function.

1.2 函数调用 Function call

  • Control of the program is transferred to the user-defined function by calling it.

  • 嵌套调用方式: 在一个函数内部调用另一个函数;

  • 递归调用方式: 在一个函数内部调用该函数自己.(直接递归&间接递归)

1.3 函数定义 Function definition

  • Function definition contains the block of code to perform a specific task.
  • When a function is called, the control of the program is transferred to the function definition. And, the compiler starts executing the codes inside the body of a function.
  • The type of arguments passed to a function(actual parameter) and the formal parameters must match, otherwise, the compiler will throw an error.
  • The return statement terminates the execution of a function and returns a value to the calling function. The program control is transferred to the calling function after the return statement.
  • return 语句至多返回一个值.
  • 函数类型, 就是返回值的类型. return 语句中表达式的类型应该与函数类型一致. 若不一致, 以函数类型为准(赋值转化).
  • 函数类型若省略, 则默认为 int.
  • The type of value returned from the function and the return type specified in the function prototype and function definition must match.

1.4 递归函数 Recursion function

  • A function that calls itself is known as a recursive function. And, this technique is known as recursion.
  • Advantages and Disadvantages of Recursion:
    • Recursion makes program elegant. However, if performance is vital, use loops instead as recursion is usually much slower.
    • That being said, recursion is an important concept. It is frequently used in data structure and algorithms. For example, it is common to use recursion in problems such as tree traversal.

变量存储类型 Variable Storage Class

Every variable in C programming has two properties: type and storage class.

  • Type refers to the data type of a variable.(char \ int \ float \ double...)
  • Storage class determines the scope, visibility and lifetime of a variable.(automatic \ external \ static \ register)

变量的存储类型是对变量的 作用域, 存储空间, 生存期 的规定

2.1 局部/自动变量 Local/Automatic Variable

The variables declared inside a block are automatic or local variables. The local variables exist only inside the block in which it is declared.

  • auto 型 变量在赋值以前, 具有不确定的值;
  • 函数被调用时分配存储空间(动态存储区, 堆栈区), 函数执行结束时自动释放所占用的存储空间;
  • 定义局部变量时, 如果缺省存储类型项, 则系统默认为 auto ;

2.2 全局/外部变量 Global/External Variable

Variables that are declared outside of all functions are known as external or global variables. They are accessible from any function inside the program.

  • 定义在函数外部, 编译时分配在 静态存储区.
  • 作用域: 从定义的位置开始, 到程序结束.
  • 全局变量如果不初始化, 则系统默认赋值为 0.
  • 对于多源文件, 使用 extern 声明外部全局变量, 可以扩大到其他源文件.

Suppose, a global variable is declared in file1. If you try to use that variable in a different file file2, the compiler will complain. To solve this problem, keyword extern is used in file2 to indicate that the external variable is declared in another file.

2.3 寄存器变量 Register Variable

Register variables were supposed to be faster than local variables.

作用: 建议系统将变量分配至 CPU 内的寄存器.

  • 在 CPU 内部, 存取速度更快;
  • 在 CPU 内部, 不在内存中, 所以无法取地址;

2.4 静态变量 Static Variable

The value of a static variable persists until the end of the program.

  • 静态局部变量(函数内定义) & 静态全局变量(函数外定义);
  • 始终存在, 不因函数运行结束而消失, 再次进入该函数时, 将保留上次的值;
  • 存放在内存的 静态存储区, 在 编译时 即为其分配存储空间, 并赋初值;(static 型变量, 只在编译时被初始化一次, 运行时不再运行初始化语句)
  • static局部变量若为赋以初值, 则由系统自动赋值:
    • 数值型变量 = 0;
    • 字符型变量 = '';

Others

传值方式

  • 值传递
    • 实参 & 形参 各占一个独立的存储空间;
    • 当函数被调用时, 系统才为形参分配临时存储空间(存放实参的值), 调用结束则收回该空间.
  • 地址传递
    • 与值传递类似, 但地址传递中,形参的临时存储空间中存放的是实参的地址, 因此被调函数中的任何操作都被处理成间接寻址, 可以影响到实参的值.
    • 因为 return 语句只能返回一个数据, 所以可以借助地址传递返回多个数据.

指针函数 & 函数指针

  • 指针函数 int* fun(); // 指针函数 fun() 返回一个 int* 类型的指针.
  • 函数指针 int (*fun)(); // 函数指针 fun 指向一个返回值为 int 类型 & 无参的函数的首地址.

函数指针变量不能进行算数运算, 因为函数指针的移动是毫无意义的.

存储区域

  • 程序存储区: 存放程序
  • 静态存储区: 存放静态变量
  • 动态存储区: 存放动态变量

全局函数 & 静态函数:

  • C 语言中, 函数默认都是 全局函数(内联函数 extern),
    • static函数只能在本文件中使用, 其他文件不能调用;
  • 使用 static 可以将函数声明为 静态函数(外部函数 static);
    • 同一源文件中, 允许全局变量和局部变量同名, 此时全局变量不起作用;

return & exit

  • return 表示 函数返回, 即该函数运行结束, 在 main 函数中和 exit 效果一样.(main函数结束, 即程序终止)
  • exit 表示 程序终止, 即退出程序的执行.

main 函数的参数:

  • C编译器允许main()函数没有参数,或者有两个参数(有些实现允许更多的参数,但这只是对标准的扩展)。
    • 第一个参数被称为argc(argument count),是命令行中的字符串数 (即 命令行输入参数的个数)。
    • 第二个参数被称为argv(argument value),是一个指向字符串的指针数组 (即 所有的命令行参数)。系统将命令行中的每个字符串存储到内存中,并且分配一个指针指向它。(使用空格把各个字符串格开)
    • 一般情况下,把程序本身的名字赋值给argv[0],接着,把第一个字符串赋给argv[1],等等。
/* 
terminal 输入命令: 
    gcc test.c -o test
    ./test i love you
输出结果:
This program is ./test .
The command line has 3 arguments:
1: i
2: love
3: you
*/
#include<stdio.h>

int main(int argc, char *argv[]) {
    int count;
    printf("The command line has %d arguments:\n", argc-1);
    for(count = 1; count < argc; count++)
        printf("%d: %s\n", count, argv[count]);
    return 0;
}

Others

  • 数组名作为函数参数时, 形参数组长度 & 实参数组长度可以不同, 因为实际传递的是数组的首地址.