C复习-函数

参考: 里科《C和指针》


int *func();

这个既可以看作是一个旧式风格的声明(只给出func的返回类型),也可以看作是一个没有参数的函数的新风格原型。这个声明必须被解释为旧式风格的声明,目的是保持与ANSI标准前的程序的兼容性。一个没有参数的函数的原型应该写成:

int *func( void );

函数的原型中,参数名不是必须的,但是写上可以给用户提供更多的信息。

应该将所有原型写在一个头文件里,然后用include包含在需要使用的文件中。这样如果需要修改某个原型只需要修改一次,也避免了多处书写原型造成的冲突。
如果程序调用一个无法见到原型的函数时,编译器会认为该函数返回一个整数值。同时,传递给函数的实参会进行缺省参数提升,即char/short转为int,float转为double

float f = xyz()
// 如果在函数调用前,编译器没看到xyz()的原型,就会认为它返回一个整型,但实际它返回的是浮点值
// 那么编译器会将二进制的浮点数以整型解释,再将其转换为float,再赋值给f

  1. 传递给函数的标量都是传值调用;
  2. 传递给函数的数组参数在行为上就像它们是通过传地址调用的那样
// 无效交换,因为是传值,所以x和y在函数内修改了并不会返回出来
void
swap(int x, int y)
{
    int temp;
    temp = x;
    x = y;
    y = temp;
}

// 有效交换
void
swap(int* x, int* y) 
{
    int temp;
    temp = *x;
    *x = *y;
    *y = temp;
}

swap(&x, &y);

声明数组参数时可以不指定长度,因为函数不会为数组元素分配内存,是通过间接访问去找数组元素的。但是函数同样无法判断数组参数的长度,所以如果需要的话必须作为参数显式传递。

void
clear_array( int array[], int n_elements) 
{
    while (n_elements > 0)
        array[--n_elements] = 0;
}

递归的两个特性:1)存在限制条件:当符合条件时停止;2)每次递归调用后越来越接近限制条件

递归的优点是代码简单清晰,如果这一优点可以补偿效率开销的话,可用。

尾递归tail recursion:递归调用是函数所执行的最后一个任务。尾递归可以改写成循环,一般能更快。

long
fac( int n )
{
	if( n <= 0 )
		return 1;
	else
		return n * fac( n - 1 );
}

可变参数:var_arg必须指定正确的类型,因为可变参数实际传递给函数时,会经历缺省参数提升,如果还想保持正确的类型,就需要指定

#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;
}

average(3, 2, 4, 6)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值