这章主要介绍了函数的相关信息,但没有涉及到函数指针高级操作,这章很简单,以下简要说下
函数定义
类型名
函数名 (形式参数)
代码块
int
func(int a, int b)
{
return a+b;
}
函数声明
以下为函数原型的格式
类型名 函数名 (形式参数);
int *func(char *str, int value);
注意,没有声明函数原型的函数,会被编译器缺省认定(默认)返回整型,这对于返回其他类型的函数是很危险的。因此,函数必须要声明原型。
函数的参数
也叫形(式)参(数),分别为值传递,和指针传递。
值传递,相当于拷贝实参的值,即使函数改变了拷贝的值,和原来的实参没影响。
指针传递,如指针、数组,改变了形参,同时也改变了实参,因为指向的内存地址相关联
#include <stdio.h>
void s1(int a, int b)
{
int temp = a;
a = b;
b = temp;
}
void s2(int *a, int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
int main(void)
{
int a = 1, b = 2;
s1(a, b); // 值传递,没有交换 a 和 b 的值
printf("a=%d, b=%d\n", a, b);
s2(&a, &b);// 指针传递,交换 a 和 b 的值
printf("a=%d, b=%d\n", a, b);
return 0;
}
ADT 和黑盒
抽象数据类型 ADT(Abstract Data Type),可以限制函数和数据定义的作用域,这个技巧也被称为黑盒(black box)。其实,用面向对象 OOP
思想这就叫封装,对外提供接口,用户不关心里面的实现。
递归
看看下面的代码,结合书中的图例,很好理解的
#include <stdio.h>
void binary_to_ascii(unsigned int value)
{
unsigned int quotient;
quotient = value / 10;
if (quotient != 0) {
binary_to_ascii(quotient);
}
putchar(value % 10 + '0');
}
int main(void)
{
int value = 12345;
binary_to_ascii(value);
return 0;
}
之后又介绍了迭代,主要是针对递归过程中产生的性能问题进行优化,这个主要看算法实现了,这里就不展开了。
可变参数列表
正常使用参数时,参数是固定的,如果要可变,需要引入 stdarg
头文件,并且使用va_list
类型和三个宏 va_start
, va_arg
, va_end
,结合实例看的更清楚些
#include <stdio.h>
#include <stdarg.h>
float average(int n_values, ...)
{
va_list var_arg;
int count;
float sum = 0;
va_start(var_arg, n_values);
for (count=0; count<n_values; count++) {
sum += va_arg(var_arg, int);
}
va_end(var_arg);
return sum / n_values;
}
int main(void)
{
printf("%f\n", average(1, 2, 3, 4, 5)); // 这里的值可以动态变化
return 0;
}