函数
1.函数调用一个无法见到原型的函数时,默认返回一个整型值。
float f;
...
f = xyz();
无法看到xyz()函数原型,返回整型值,然后强制转换为float类型。
函数的参数
1.传递给函数的标参是传值调用
2.传递给函数的数组参数是通过传址调用的
3.声明数组参数时不指定它的长度是合法的,函数并不为数组元素分配内存
void clear_array(int array[], int n_elements)
{
while (n_elements > 0)
{
array[--n_elements] = 0;
}
}
ADT和黑盒
ADT抽象数据类型,限制函数和数据定义的作用域,这个技巧也被称为黑盒,由接口和实现组成,限制对模块内部的访问是通过static实现的。
例子如下:
addlist.h
#define NAME_LENGTH 30
#define ADDR_LENGTH 100
#define PHONE_LENGTH 11
#define MAX_ADDRESSES 1000
char const* lookup_address(char const* name);
char const* lookup_phone(char const* name);
addlist.c
#include <stdio.h>
#include "addrlist.h"
static char name[MAX_ADDRESSES][NAME_LENGTH];
static char address[MAX_ADDRESSES][ADDR_LENGTH];
static char phone[MAX_ADDRESSES][PHONE_LENGTH];
static int find_entry(char const* name_to_find)
{
int entry;
for (entry = 0; entry < MAX_ADDRESSES; entry++)
{
if (strcmp(name_to_find, name[entry]) == 0)
{
return entry;
}
}
return -1;
}
char const* lookup_address(char const* name)
{
int entry;
entry = find_entry(name);
if (entry == -1)
{
return NULL;
}
else
{
return address[entry];
}
}
char const* lookup_phone( char const * name)
{
int entry;
entry = find_entry(name);
if (entry == -1)
return NULL;
else
return phone[entry];
}
递归
1.递归函数:
void binary_to_ascii(unsigned int value)
{
unsigned int quotient;
quotient = value / 10;
if (quotient != 0)
binary_to_ascii(quotient);
putchar(value % 10 + '0');
}
函数被调用时,它的变量空间创建于运行时的堆栈中,以前调用函数的变量仍然保留在堆栈上,但它们被新函数的变量所掩盖,不能被访问。
可变参数列表
1.stdarg宏
此头文件声明了一个类型va_list和三个宏–va_start、va_arg、va_end。
#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 += 1)
{
sum += va_arg(var_arg, int);
}
va_end(var_arg);
return sum / n_values;
}
va_list类型的var_arg用于访问参数列表的未确定部分
通过va_start来初始化,此过程把var_arg变量设置为指向可变量参数部分的第一个变量
va_arg函数接受两个参数:va_list变量和参数列表中下一个参数的类型,返回这个参数的值,并使var_arg指向下一个可变参数。
在访问完最后一个可变参数之后,调用va_end;
注意:
这些宏无法判断实际存在的参数的数量和每个参数的类型。
小结
1.一个函数被调用,编译器若无法看到它的任何声明,假定返回一个整型值。
2.函数的形参通过传值的方式,函数形参中的数组通过传址的方式。
3.尾部递归很容易改写为循环的形式,效率更高一点。
4.参数列表中可变部分的参数实际传递给函数时,将经历缺省参数提升,可变部分的参数只能从第一个到最后一个依次访问。