函数声明要放在main函数前面,这样就可以了
#include stdio.h
#include stdlib.h
p1();
int main()
{
p1();
}
p1()
printf("********\n");
printf ("welcome \n");
这段论述包含了许多概念性错误,这些概念错误在许多C语言书中都同样普遍存在.为了说明这些错误,首先来回顾一下C语言演变和发展的一些情况.
最早,C语言的代码可以这样写:
main(){?printf("hello,world!\n");}
注意,这段代码对标识符printf没有进行任何说明.这是因为printf()函数的返回值为int类型.当时的C语言规定,对于没有任何说明的函数名,编译器会默认为返回值为int类型,所以呢对这样的函数名可以不做任何说明.那个时期的C语言,很多情况下int可以不写.例如main()函数返回值的类型为int就可以不写.
在C语言早期,尽管有时不需要对函数名进行说明,但有些情况下对函数名进行说明还是必须的,比如:
不难注意到这种对函数名的说明非常简单,这是最早期的一种函数类型说明的形式.这种说明只着重说明函数名是一个函数及其返回值类型,如果程序员在调用函数时存在参数类型或个数方面的错误编译器是无法察觉的,因为函数类型说明中"()"内没有任何信息.
这种办法只说明了函数名与()进行运算的结果也就是函数返回值的数据类型,无法进一步检查参数方面的错误是这种写法的不足之处.
如果不写函数类型说明,也可以把函数定义写在函数调用之前:
这表明函数定义也具有对函数名的类型加以说明的效果,所以呢从这个意义上来说,函数定义也是一种对函数类型的说明.这种办法可以检查出函数调用时在参数个数和类型方面的错误.
使用这种办法,不但可以检查函数调用时参数类型和个数方面的错误,同时解决了源代码的组织问题,因为程序员不必再考虑该把哪个函数写在前面、哪个写在后面这种无聊的问题了.这种办法全面地说明了函数名的数据类型.此外要说明的是,把形参及其数据类型写在"()"内形式的函数定义也属于函数原型(Function Propotype)的范畴.
由此可见,古老的、不对参数进行任何说明的函数类型说明方式、函数定义以及函数原型式的函数类型说明方式都具有说明函数名意义的效用.从这个意义上讲它们都是函数声明.在C语言中,声明(Declaration)这个词的本义就是指定标识符的意义和性质(A declaration specifies the interpretation and attributes of a set of identifiers.),某个标识符的定义(Definition)同时也是这个标志符的"声明"(Declaration).函数定义(Function definition)则意指包括函数体.(A definition of an identifier is a declaration for that identifier that: ......for a function, includes the function body;).函数原型则特指包括说明参数类型的函数声明,它同样包含用这种方式写出的函数定义.
现在回过头来看样本中的第一句话:"对函数的"定义"和"声明"不是一回事".由于函数定义本身就是一种函数声明,怎么可以说它们不是一回事呢?这句话的逻辑就如同说"男人"和"人"不是一回事.你可以说男人和女人不是一回事,因为他们没有交集.但没法说男人和人不是一回事,因为男人是人的子集,男人就是人的一种,怎么可以说男人和人不是一回事呢?
那么,不带函数体的函数声明应该如何称呼呢?在C语言中,它们叫被做"函数类型声明"(Function type declaration).函数类型声明最主要的特点是声明了函数名是一个函数及其返回值的类型,如果也声明了参数的类型,则是函数原型式的函数类型声明.
样本中的"而函数的声明的作用则是把函数的名字,函数类型以及形参的类型、个数和顺序通知编译系统,以便在调用该函数时进行对照检查(例如,函数名是否正确,实参与形参的类型和个数是否一致),它不包括函数体"这句话同样不通.其主要错误是它混淆了"函数原型式类型声明"与"函数声明"这两个概念,前一个概念只是后一个概念的子集.函数声明中不但包含"函数类型声明",也包含"函数定义"和老式的"函数类型声明".由于函数定义本身就是一种函数声明,所以无法断定函数的声明是否包括函数体;而且老式的函数类型声明(例如double sqrt();)也属于函数声明,这种函数声明并不检查参数类型及个数方面的错误.此外函数声明也并没有检查"函数名"正确与否的功能.
这段文字中的"函数类型"这个概念也有错误,函数类型所描述的不但包括函数返回值类型,也可能一并描述参数的个数和类型(如果是函数原型),所以呢不能与"形参的类型、个数"相提并论.
main()函数
在各种C语言书上,能看到各式各样main()函数的写法,简直令人无所适从,这是这么回事?原因主要有两个:一个是随着C语言的发展和演化,main()函数的写法也在不断变化;另外,某些书籍写法不规范或误导的现象也同时存在.
main(){?printf("hello,world\n");}
#include stdio.hmain(){?printf("hello,world\n");}
int main(void) { /*. . .*/}
为什么要容忍?因为有许多老式的代码还在用.
那又为什么说KR对新标准的认同呢?<
#include stdio.hmain(argc,argv)int argc;char *argv[];{?/*...... */?return 0;}
改成了:
#include stdio.hmain(int argc, char *argv[]){?/*...... */?return 0;}
这里出现的"return 0;"是怎么回事?这在现代C语言中已经是司空见惯了,它返回给操作系统一个值以表明程序是在何种状态下结束的.但在另一段代码中,KR似乎又走得太远:
#include stdio.hmain(int argc,char *argv[]){?int found = 0 ;?/*......计算found的值 */?return found;}
这个实在有些"标新立异",居然把计算结果返回给了操作系统,颇有突破常规之嫌.
#include stdio.hvoid main(){?printf("This is a C program.\n");}
但是不管怎么说,这种写法最多是某些编译器的一种"方言土语",如果没有特殊理由,比如仅仅是工作在某个特殊环境,且仅仅使用特定的编译器而根本不考虑程序的可移植性,为什么不写普遍适用的形式呢?
还有什么样的main()函数?很多编译器都支持下面的main()的写法:
int main(int argc, char *argv[], char *env[]){?/* */?return 0;}
什么叫环境变量?简单地讲可以理解为操作系统记录的一些数据,比如计算机的名字,操作系统放在哪里等等.应用程序在运行时可能要用到这些信息,这时可以通过env这个参数来获得.
如果编译器不支持main()的第三个参数怎么办?标准库函数也可以达到同样的目的.
#include stdlib.hchar *getenv(const char *name);
下面这种风格如何?
#include stdio.hint main(){?printf("This is a C program.\n");?return 0;}
main(argc,argv)int argc;char *argv[];{?/*...... */?return 0;}
都属于历史的垃圾.
见过在main()的函数体的"}"之前前写一句getch();,这个是怎么回事?这个是时代的产物.在PC从DOS时代转变为Windows时代的过程中,DOS时代开发的IDE(主要是TC)无法在运行程序后显示输出结果,为了在运行后从容仔细地观察一下运行结果再返回IED界面,加上了这么一句,人为地延长程序运行时间(因为getch()会等待用户输入一个字符).但这与main()本身的结构无关.这条语句不具备普遍意义,只是将就过时的IDE的一种权宜之计而已.所谓不具备普遍意义是指,第一,真正的程序往往不需要这条语句,就是说这条语句与程序功能无关;第二,getch()这个函数并不是标准函数,只有个别的编译器才支持它,在其他编译器上写这条语句,很可能行不通.
为什么不用getchar()这个标准库函数呢?getchar()的功能和getch()有点区别,前者会在标准输出设备上显示用户键入的字符,这显得很不利索,而后者则不会显示用户所键入的字符,更接近"Press Any Key to continue......"的效果.
有的代码在main()函数结束前写system("PAUSE");,是否也是这个意思?是的.这也是一种人工制造的"请按任意键继续. . .",与程序功能结构无关,只是为了方便地观察输出结果.但是这种写法比调用getch()要好,因为system()函数是标准库函数,各个编译器都提供支持.
int main( void ){?/* */?return 0;}
和
int main( int argc, char *argv[] ){?/* */?return 0;}
这种说法对吗?
还有一种写法:
int main( void ){?return EXIT_SUCCESS;}
那个EXIT_SUCCESS是怎么回事?
return EXIT_SUCCESS;是与return 0;等价的一种文雅的写法.EXIT_SUCCESS是在stdlib.h中定义了的符号常量,返回这个值表示程序任务完成后程序退出.在stdlib.h定义的另一个符号常量EXIT_FAILURE,通常用于程序无法完成任务而退出.
实在太眼花缭乱了,需要记住这么多吗?显然没必要.很多东西都是历史原因遗留下的垃圾.
如果学习C语言,应该记住或使用哪种呢?显然是:
第一,他们普遍适用,不存在可移植性的问题;
第二,就目前看,他们不存在任何过时或即将过时的成分.当然,如果喜欢文雅,不写return 0;而写EXIT_SUCCESS也可以. 顺便说一句,有的学习者记不住带参数main()函数两个形参的名字.其实这两个形参的名字也可以自己取,不一定用那两个名字,只要记住类型就可以了.第二个参数的类型也可以是char **,这和原来的是等价的.
函数声明它为编译器提供了有用的信息,编译器在翻译代码的过程中,只有见到函数原型(这里即可以是声明也可以是定义)之后才知道这个函数的名字、参数类型和返回值,这样碰到函数调用时才知道怎么生成相应的指令,所以函数原型必须出现在函数调用之前,这也是遵循"先声明后使用"的原则.
注意上面说的函数原型是包括函数声明和定义两种形式的.
另外还有一种特殊情况,就是
隐式声明:
隐式声明的函数返回值类型都是int;
如下
#includestdio.h
main()
int jiec(int n)
int y=1;int i;
for(i=1;i=n;i++)
y=y*i;
return(y);
这个程序也是可以运行的.主要返回值为int.
定义函数
C 语言中的函数定义的一般形式如下:
return_type function_name( parameter list )
body of the function
在 C 语言中,函数由一个函数头和一个函数主体组成.下面列出一个函数的所有组成部分:
返回类型:一个函数可以返回一个值.return_type 是函数返回的值的数据类型.有些函数执行所需的操作而不返回值,在这种情况下,return_type 是关键字 void.
函数名称:这是函数的实际名称.函数名和参数列表一起构成了函数签名.
参数:参数就像是占位符.当函数被调用时,您向参数传递一个值,这个值被称为实际参数.参数列表包括函数参数的类型、顺序、数量.参数是可选的,也就是说,函数可能不包含参数.
函数主体:函数主体包含一组定义函数执行任务的语句.
第一,如果你没有看错就是你的书错了,只有int和char类型的函数不必声明
①.就是上面我说的
对于第二点,很好解释,因为声明的目的在于告诉编译器有这么个自定义函数,返回类型是什么,如果被调函数定义在主调函数之前,那么编译器自然就知道了这个函数
再说一句,写函数声明是编写程序的良好习惯
不要把C++的概念强加给C
"函数定义"是指对函数功能的确立,包括指定函数名,函数值类型、形参类型、函数体等,它是一个完整的、独立的函数单位.
而"函数声明"的作用则是把函数的名字、函数类型以及形参类型、个数和顺序通知编译系统,以便在调用该函数时系统按此进行对照检查(例如函数名是否正确,实参与形参的类型和个数是否一致).
在书写形式上,函数声明可以把复数头部复制过来,在后面加一个分号;而且在参数表中可以只写各个参数的类型名,而不必写参数名.
C语言不同于Java语言,在Java语言中,在一个类中,定义函数/方法后,在调用时不需要声明.在C语言中定义函数后,在使用前,需要在main函数前进行声明,否则会报错.
或者将函数定义在main函数的前面,则不需要声明
注意:在其他函数中调用自定义的函数时,也是要在调用者前进行声明,或者定义在调用者前,否则会报错无法使用
int getMax(int a, int b) {
if (a b) {
return a;
else {
return b;
void main() {
printf("%d\n", t);
getchar();
扩展资料:
关于函数的概念我们可以这样理解,函数是一个功能的集合,它可以根据输入完成特写的功能,并将结果输出.当然有时候函数只是为了实现一些特写功能而并不一定要有输入或输入.
我们想要自己编写一个函数需要编写两部分内容:声明和定义.函数的声明就是告诉编译器我们想要定义一个函数,并明确规定其返回值(输出)、函数名、参数表(输入).声明函数的语法如下:
type function_name(type var);
以上就是土嘎嘎小编为大家整理的c语言隐式函数声明相关主题介绍,如果您觉得小编更新的文章只要能对粉丝们有用,就是我们最大的鼓励和动力,不要忘记讲本站分享给您身边的朋友哦!!