C语言函数声明以及函数原型超详细讲解示例

C语言代码由上到下依次执行,原则上函数定义要出现在函数调用之前,否则就会报错。但在实际开发中,经常会在函数定义之前使用它们,这个时候就需要提前声明。

所谓声明(Declaration),就是告诉编译器我要使用这个函数,你现在没有找到它的定义不要紧,请不要报错,稍后我会把定义补上。

函数声明的格式非常简单,相当于去掉函数定义中的函数体,并在最后加上分号;,如下所示:

dataType functionName( dataType1 param1, dataType2 param2 ... );

也可以不写形参,只写数据类型:

dataType functionName( dataType1, dataType2 ... );

函数声明给出了函数名、返回值类型、参数列表(重点是参数类型)等与该函数有关的信息,称为函数原型(Function Prototype)。函数原型的作用是告诉编译器与该函数有关的信息,让编译器知道函数的存在,以及存在的形式,即使函数暂时没有定义,编译器也知道如何使用它。

有了函数声明,函数定义就可以出现在任何地方了,甚至是其他文件、静态链接库、动态链接库等。

【实例1】定义一个函数 sum(),计算从 m 加到 n 的和,并将 sum() 的定义放到 main() 后面。

#include<stdio.h>
//函数声明
intsum(int m,int n);//也可以写作int sum(int, int);
intmain(){
int begin =5, end =86;
int result =sum(begin, end);
printf("The sum from %d to %d is %d\n", begin, end, result);
return0;
}
//函数定义
intsum(int m,int n){
int i, sum=0;
for(i=m; i<=n; i++){
        sum+=i;
}
return sum;
}

我们在 main() 函数中调用了 sum() 函数,编译器在它前面虽然没有发现函数定义,但是发现了函数声明,这样编译器就知道函数怎么使用了,至于函数体到底是什么,暂时可以不用操心,后续再把函数体补上就行。

【实例2】定义两个函数,计算1! + 2! + 3! + ... + (n-1)! + n!的和。

#include<stdio.h>
// 函数声明部分
longfactorial(int n);//也可以写作 long factorial(int);
longsum(long n);//也可以写作 long sum(long);
intmain(){
printf("1!+2!+...+9!+10! = %ld\n",sum(10));
return0;
}
//函数定义部分
//求阶乘
longfactorial(int n){
int i;
long result=1;
for(i=1; i<=n; i++){
        result *= i;
}
return result;
}
// 求累加的和
longsum(long n){
int i;
long result =0;
for(i=1; i<=n; i++){
        result +=factorial(i);
}
return result;
}

运行结果:

1!+2!+...+9!+10! = 4037913

初学者编写的代码都比较简单,顶多几百行,完全可以放在一个源文件中。对于单个源文件的程序,通常是将函数定义放到 main() 的后面,将函数声明放到 main() 的前面,这样就使得代码结构清晰明了,主次分明。

使用者往往只关心函数的功能和函数的调用形式,很少关心函数的实现细节,将函数定义放在最后,就是尽量屏蔽不重要的信息,凸显关键的信息。将函数声明放到 main() 的前面,在定义函数时也不用关注它们的调用顺序了,哪个函数先定义,哪个函数后定义,都无所谓了。

然而在实际开发中,往往都是几千行、上万行、百万行的代码,将这些代码都放在一个源文件中简直是灾难,不但检索麻烦,而且打开文件也很慢,所以必须将这些代码分散到多个文件中。对于多个文件的程序,通常是将函数定义放到源文件(.c文件)中,将函数的声明放到头文件(.h文件)中,使用函数时引入对应的头文件就可以,编译器会在链接阶段找到函数体。

到此这篇关于C语言函数声明以及函数原型超详细讲解示例的文章就介绍到这了,更多相关C语言函数声明内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 浅谈C语言中strcpy,strcmp,strlen,strcat函数原型

    实例如下: //strcat(dest,src)把src所指字符串添加到dest结尾处(覆盖dest结尾处的'\0')并添加'\0' char *strcat(char * strDest, const char *strSrc) { char *res=strDest; assert((strDest!=NULL)&&(strSrc!=NULL)); while(*strDest)strDest++; while(*strDest=*strSrc) { strDest++; strSrc

  • C语言typedef与复杂函数声明问题的深入解析

    下面是三个变量的声明,我想使用typedef分别给它们定义一个别名,请问该如何做?>1:int *(*a[5])(int, char*);>2:void (*b[10]) (void (*)());>3. doube(*)() (*pa)[9];答案与分析:对复杂变量建立一个类型别名的方法很简单,你只要在传统的变量声明表达式里用类型名替代变量名,然后把关键字typedef加在该语句的开头就行了. >1:int *(*a[5])(int, char*);//pFun是我们建的一个类型

  • C语言中的隐式函数声明

    1 什么是C语言的隐式函数声明 在C语言中,函数在调用前不一定非要声明.如果没有声明,那么编译器会自动按照一种隐式声明的规则,为调用函数的C代码产生汇编代码.下面是一个例子: int main(int argc, char** argv) { double x = any_name_function(); return 0; } 单纯的编译上述源代码,并没有任何报错,只是在链接阶段因为找不到名为any_name_function的函数体而报错. [smstong@centos192 test]$

  • C语言中函数声明与调用问题

    假如函数在调用它之前定义可以不用声明 实际上,如果在函数调用前,没有对函数作声明,则编译系统会吧第一次遇到的该函数的形式(函数定义或者函数调用)作为函数的声明,并将函数默认值类型认为int型 比如有您调用的是void max(int a,int b)系统就会把该函数当做int max(int a,int b);

  • C语言函数声明以及函数原型超详细讲解示例

    C语言代码由上到下依次执行,原则上函数定义要出现在函数调用之前,否则就会报错.但在实际开发中,经常会在函数定义之前使用它们,这个时候就需要提前声明. 所谓声明(Declaration),就是告诉编译器我要使用这个函数,你现在没有找到它的定义不要紧,请不要报错,稍后我会把定义补上. 函数声明的格式非常简单,相当于去掉函数定义中的函数体,并在最后加上分号;,如下所示: dataType functionName( dataType1 param1, dataType2 param2 ... ); 也

  • C++函数模板与重载解析超详细讲解

    目录 1.快速上手 2.重载的模板 3.模板的局限性 4.显式具体化函数 5.实例化和具体化 6.重载解析 6.1 概览 6.2 完全匹配中的三六九等 6.3 总结 7.模板的发展 1.快速上手 函数模板是通用的函数描述,也就是说,它们使用泛型来定义函数. #include<iostream> using namespace std; template <typename T> void Swap(T &a,T &b);//模板原型 struct apple{ st

  • C语言可变参数与内存管理超详细讲解

    目录 概述 动态分配内存 重新调整内存的大小和释放内存 概述 有时,您可能会碰到这样的情况,您希望函数带有可变数量的参数,而不是预定义数量的参数.C 语言为这种情况提供了一个解决方案,它允许您定义一个函数,能根据具体的需求接受可变数量的参数.下面的实例演示了这种函数的定义. int func(int, ... ) { . . . } int main() { func(2, 2, 3); func(3, 2, 3, 4); } 请注意,函数func()最后一个参数写成省略号,即三个点号(...)

  • C语言函数超详细讲解下篇

    目录 前言 函数的声明和定义 函数声明 函数定义 举例 简单的求和函数 把加法单独改写成函数 添加函数声明 带头文件和函数声明 静态库(.lib)的生成 静态库文件的使用方法 函数递归 什么是递归? 递归的两个必要条件 练习1 一般方法 递归的方法 练习2 一般方法 递归方法 练习3 一般方法 递归方法 练习4 一般方法 递归方法 递归与迭代 递归隐藏的问题 如何改进 选递归还是迭代 总结 前言 紧接上文,继续学习函数相关内容. 函数的声明和定义 函数声明 告诉编译器有一个函数叫什么,参数是什么

  • C语言超详细讲解指向函数的指针

    目录 一.函数的指针 二.指向函数的指针变量 三.调用函数的两种方式 四.指向函数的指针的作用 五.用指向函数的指针作函数参数(重点) 六.为什么要将指向函数的指针变量作为函数的形参(重点) 一.函数的指针 首先,函数名代表函数的起始地址,调用函数时,程序会从函数名获取到函数起始地址,并从该地址起执行函数中的代码,函数名就是函数的指针,所以我们可以定义一个指向函数的指针变量,用来存放函数的起始地址,这样一来,就可以通过该变量来调用其所指向的函数. 二.指向函数的指针变量 定义指向函数的指针变量

  • C语言函数超详细讲解上篇

    目录 前言 1.函数是什么? 2.C语言中函数的分类 2.1 库函数 2.1.1 如何学会使用库函数 2.1.2 自定义函数 3.函数的参数 3.1 实际参数(实参) 3.2 形式参数(形参) 4.函数的调用 4.1 传值调用 4.2 传址调用 4.3 练习 4.3.1 判断一个数是不是素数 4.3.2 判断一年是不是闰年 4.3.3 二分查找 4.3.4 数值自增增加1 5.函数的嵌套调用和链式访问 5.1 嵌套调用 5.2 链式访问 总结 前言 本文主要学习函数的相关内容. 1.函数是什么?

  • C语言超详细讲解函数栈帧的创建和销毁

    目录 1.本节目标 2.相关寄存器 3.相关汇编指令 4.什么是函数栈帧 5.什么是调用堆栈 6.函数栈帧的创建和销毁 (1).main函数栈帧的创建与初始化 (2).main函数的核心代码 (3).Add函数的调用过程 (4).Add函数栈帧的销毁 (5).调用完成 7.对开篇问题的解答 1.本节目标 C语言绝命七连问,你能回答出几个? 局部变量是如何创建的?为什么局部变量不初始化其内容是随机的?有些时候屏幕上输出的"烫烫烫"是怎么来的?函数调用时参数时如何传递的?传参的顺序是怎样的

  • C语言超详细讲解getchar函数的使用

    目录 一.getchar 函数 二.缓冲区 1.什么是缓冲区 2.为什么要存在缓冲区 3.缓冲区的类型 4.缓冲区的刷新 三.getchar 函数的正确使用 1.getchar 的换行问题 2.getchar 与 scanf 的混合使用 一.getchar 函数 从上面的介绍来看,我们要正确使用getchar函数,首先得了解什么是缓冲区. 二.缓冲区 1.什么是缓冲区 缓冲区又称为缓存,它是内存空间的一部分. 也就是说,在内存空间中预留了一定的存储空间,这些存储空间用来缓冲输入或输出的数据,这部

  • C语言超详细讲解字符串函数和内存函数

    目录 字符串函数 长度不受限制的字符串函数 strlen strcpy strcat strcmp 长度受限制的字符串函数介绍 strncpy strncat strncmp 字符串查找以及错误报告 strstr strtok strerror 内存操作函数 memcpy memmove memcmp 字符串函数 长度不受限制的字符串函数 strlen size_t strlen ( const char * str ) 求字符串长度: 字符串以'\0' 作为结束标志,strlen函数返回的是在

  • C语言超详细讲解函数指针的运用

    目录 前言 计算器的例子 回调函数 转移表 前言 前面我们学习了各种各样的指针类型,有些指针可以说是稀奇百怪,特别是函数指针,有些朋友可能觉得,函数指针有些多余,调用函数为什么要用指针调用,直接调用不好吗? 接下来我们从具体的实例来回答同学们的问题,加深对函数指针的理解. 计算器的例子 接下来我们写一个简单的计算器程序,完成不同的计算功能比如加减乘除: #include <stdio.h> //相加函数 int add(int a, int b) { return a + b; } //相减函

随机推荐