函数(一)

基础

        函数与变量一样,必须先声明再使用。如果函数写在调用函数之前,则不需要进行声明。函数声明格式与java中抽象函数类似,但不需要写形参名,也叫函数原型。如下:

#include <stdio.h>
int sum(int,int);//函数声明
int main(int argc, const char * argv[]) {
    int a = 256;
    char b = 127;
    printf("%d",sum(a,b));//调用函数
    return 0;
}
int sum(int a,int b){//定义函数
    return a + b;
}

分类

        函数可以是外部的(默认情况下)或者静态的。外部函数可以被其他文件中的函数调用,而静态函数只可以在定义它的文件中使用。
        使用static修饰的函数是静态函数,其目标之一就是创建一个特定模块所私有的函数。
        通常使用关键字extern来声明在其他文件中定义的函数。

函数原型

        1,函数原型的声明即可在调用函数的外面,也可在调用函数之内。

int main(void){
    int imin(int,int);//在内部声明函数原型
    imin(3,5);
}

        2,如果函数不需要参数,需在圆括号内传入void关键字,而不是直接写()。因为不传的话,编译器不会进行参数校验。

        3,对于可变参数其原型定义为:返回值 函数名(可确定类型的类型,...);,如int printf(char*,...);这种类型表明第一个参数为字符串,而后面的参数不确定。

递归

        递归就是当前函数自己调用自己。其主要有以下性质:

        1,位于递归调用前的语句与各级被调函数具有相同的执行顺序。

        2,位于递归调用后的语句的执行顺序与各级被调函数的顺序相反。如第1级调用第2级,第2级调用第3级……,那么在递归函数之前的语句的执行顺序就是:第1级的先执行,第2级的次之,第3级的再次之,依此类推;而位于递归后的语句执行顺序为:最后一级先执行,倒数第二级次之,倒数第三级再次之,依此类推。如下函数为计算二进制:

void count(unsigned long num){
    int b = num % 2;
    if(num >= 2){
        count(num/2);
    }
    printf("%d",b);
}

        说明:一个数%2就是它最低位的值(奇数的最低位肯定为1,偶数的最低位肯定是0)。如果一个数不小于2,那么该数还可以拆分成二进制(0,1的二进制分别为其本身),计算完最低位后需要再计算其余位的二进制数,因为递归当前数除以2的值。

函数指针

基础

        函数也有地址,因为函数的机器语言实现是由载入到内存的代码组成的,因为函数也有起始地址。函数指针中存储的就是该函数的起始地址。它主要用于将一个函数当作另一个函数的参数进行传递。

声明

        与声明指向数据的指针类似,声明函数指针时也必须声明它指向的函数类型。而函数类型要指向函数的返回类型及参数类型。

        如void toUpper(char*)函数,它的指针声明为void (*pf)(char*),第一个小括号表明pf是一个指针,小括号外面的为该指针指向的类型。第二个小括号又表明指针指向的是函数,并且参数为char*类型,同时返回值为void。如果除掉第一个小括号,那么代表pf是一个函数,它的返回值为void*,参数为char*。

        从上面可以看出,声明一个函数指针最简单的方法就是:在函数原型中,用(*pf)形式的表达式代替掉函数名。这样就声明了一个指向特定类型的函数的函数指针。

赋值及使用

        有了函数指针之后,就需要将函数的地址赋值给该指针,在这种场合中,函数名就代表着函数的首地址,这点和数组名一样。

        函数指针指向了函数,那么也可以使用指针来访问函数。如下:

void test() {
	puts("test");
}
int main(void) {
	void (*pf)() = test;//函数代表地址,直接赋值给pf即可
	(*pf)();//使用指针访问函数
	pf();//也可以这样用
}

        使用指针访问函数有上述两种形式:使用fp()或者(*fp)()形式来调用函数,但建议使用第一种。

内联函数

        调用函数通常需要一定的时间开销:建立调用、传递参数、跳转到函数并返回。为了减少函数调用时间,可以使用宏函数。c99还提供了另一种方法:内联函数。

        创建方法:在函数声明中使用inline关键字进行修饰。首次使用内联函数前,在文件中对内联函数进行定义。编译器看到内联函数的声明后,会使用函数体代替函数的调用,其效果如同在函数调用处输入了内容函数的函数体。

inline void haha(){
	puts("haha");
}
void test() {
	haha();
}

注意

        1,内联函数没有预留它的代码块,所以无法获取内联函数的地址。

        2,内联函数应该比较短小,不是必须短小。因为对于很长的函数,调用函数的时间比函数执行所花费的时间少很多,此时使用内联函数就很没必要了。

        3,内联函数的定义和调用必须处于同一文件中。因此,内联函数必须具有内部链接(防止别的文件中也定义了相同的函数)。如果多个文件使用相同的内联函数,应该将内联函数写在头文件中(头文件中一般不写可执行代码,但对内联函数是个例外),然后这些文件引用相同的头文件。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值