函数原型,函数声明,函数定义,他们的三角关系

来源:互联网 发布:仟游软件科技有限公司 编辑:程序博客网 时间:2024/05/01 04:03

 前景提示:

   c语言的标准从K&Rc,c89(ANSI c),c99,c11不断的发展,新标准不断的提出。但是,目前大部分编译器对c89完全支持,其他的标准可能就只是部分支持。c89是在K&Rc的基础发展而来,所以,K&R c 中的一些老式风格,许多编译还是支持。这就为我编写移植良好的程序带来许多问题。


函数定义:声明  +  具体实现 。它向编译器提供函数的信息,以及调用函数时的操作。

int fun( int a, int b){a + b;printf("%d",a);return 0;}

编译器得知的信息:

        (1)函数的返回值

         (2)参数的类型,参数的个数。

这都是声明做的工作,所以在后期调用函数时,编译器会检查函数的使用情况,确保函数正确调用。

函数实现就是 { .... } 花括号中的代码


老式的代码风格

int fun( a , b )int a ;int b;{a + b;printf("%d",a);return 0;}
区别:参数的类型写在参数的列表和左花括号之间。

缺点:编译器只会记住函数 的返回类型,关于参数个数以及类型,编译器不管

#include<stdio.h>int fun();//编译器记住的信息int main( void ){int a = 1;int b = 2;fun( a );}int fun( a,  b )int a;int b;{printf("%d",a);return 0;}
gcc 编译完全没问题,并且不会报错,或警告


函数声明:向编译器提供函数的信息,确保函数正确调用。

         一般,向函数提供编译的信息有两种,一种是是没有参数的列表(老式风格),编译器只会记住返回值。另一种是函数原型(新式风格,现在我们一般写的,所提倡的)。

函数原型

int fun( int a, int b);
优点:编译器知道参数类型,个数,当参数不匹配,会向用户发错警告。

 还有些关于原型你必须知道的事。

       (1)函数原型像变量一样具有作用域。

int main( void ){{int fun( int a ,int b);fun();}......{int fun( int a ,int *b);fun();}}
虽然你可能不这样写,但是编译器还是不会报错,你两个fun函数不一致,一定有哪里写错了,最好函数原型有文件作用域,放在头文件中,或者位于main函数前。

       (2)函数原型中可以不写参数名

int fun( int , int );
编译器不关心变量名,实际上,代码翻译成机器码,根本没有变量名,有的只是一个个地址(不同地址对于不同变量)。但是程序是给人看的,所以在函数原型中的变量名最好能体现变量在函数中的作用,让程序员很快知道你函数的功能,这是一个不错的代码习惯。


没有参数列表(老式风格)

int fun( );
这种写法很常见,也许曾经就出现在你的代码中。你会说我这是一个参数为0的函数,可是编译器却不这么认为,即使你调用函数fun(a ,b ,c ..... ),这样写也不好出错。原因在于,只要声明函数时,不使用函数原型,编译器都不会记住参数相关信息。所以,区分有没有参数应该加void

int fun( void );int fun( );//二义性,是新风格无参函数,还是旧风格 忽略参数列表的声明


再提一点:函数声明省略时,系统会添加一个返回值为int 同名函数声明

#include<stdio.h>//int fun();  编译自动添加int main( void ){float a = fun();printf("%lf",a);}float fun(){return 3.14;}
sorry

当你写的函数返回值为int,你忽略了编译可能不发出警告,因为它默认帮你添加。当函数返回值是其他类型,记得写函数原型很有必要。


函数原型:函数声明的一种情况。

 

关于他们的三角关系,有了一个大致的了解


定义实现了声明的功能,但不等同与声明。

原型是声明的一种 。

定义只能一次,声明可有多次(是不是想起,变量的定义和声明 )。


以上的所有情况,你或许见过,或许没见过,但是他们是真是存在的,好的代码风格,程序会有好的移植性

        

0 0