对于程序来讲,函数的地位是不言而喻的。下面先给出函数的定义,然后根据定义分析C语言中的函数。
函数定义:
类型
函数名(形式参数)
代码块
由定义可以看出函数主要包括四部分:函数类型、函数名、函数形参、函数代码块。
函数类型:指明了函数返回值的类型,是整数、浮点数、指针甚至是结构体等等。需要注意的两点:1、如果类型是void,则没有返回值。如果是void *型的返回值,那可以返回任意类型的指针,这是ANSI C标准定义的,void *可以是任意类型的指针。2、返回值的类型应该与函数定义的类型相同,否则编译器会对它进行强制类型转换。
函数名:就是指函数的名称,注意一点就是函数名可以作为函数的参数进行传递,此时函数名是函数的起始地址。这一点在回调函数用有应用。
test.c示例源码:
#include <stdio.h> void fun(void) {} void main(void) { printf("fun addr = %p\n", fun); return; }编译:gcc test.c
执行:./a.out
结果:fun addr = 0x80483e4
代码块:包含了局部变量的声明和函数调用时需要执行的语句。
函数形参:C语言中函数的所有参数均以“传值调用”方式进行传递,这就是说函数将获得参数值的一份拷贝。传递数组时其实是传递的数组的地址值,类似的有指针、函数名等。对于形参,记住两个规则:
1、传递给函数的标准参数是传值调用的。
2、传递给函数的数组参数在行为上就像它们时通过传址调用的那样。
函数定义完成后要想使用,一般会进行函数声明。函数声明就是告诉编译器函数的特定信息(类型、参数等)。有两种方式告诉编译器函数的信息:
一 如果同一源文件的前面已经出现了该函数的定义,编译器就会记住它的参数数量和类型,以及函数的返回值类型。
二 使用函数原型向编译器提供函数信息。
技巧:函数原型必须与函数定义匹配,把函数原型包含在定义函数的文件中可以使编译器确认它们之间的匹配。
示例程序:
/*File name : main.c*/ #include <stdio.h> #include "fun.h" void main(int argc, char **argv) { int a = 1, b = 2; printf("a + b = %d\n", fun(a, b)); return; }
/*File name : fun.h*/ extern int fun(int, int);
/*File name : fun.c*/ #include "fun.h" int fun(int num1, int num2) { return num1 + num2; }编译:gcc main.c fun.c
执行:./a.out
结果:a + b = 3