C语言-函数
C语言中的函数,类似于在C#和Java中中的方法,函数一般分为可以主函数(一般一个PC程序只有一个主函数,也就是程序的入口,这是编译器的约定,如果你觉得不爽可以写链接器脚本直接,可以不使用main作为程序的入口),自定义函数(想想面向对象中必备的各种类,各种Helper,Util吧),库函数(stadio提供的printf和scanf函数),函数的定义和使用比较简单,先看一段代码:
1 2 3 4 5 6 7 8 9 10 11 12 | #include<stdio.h> void main(){ printf ( "sum相加%d\n" ,sum(100,200)); printf ( "div求余%d" , div (300,100)); getchar (); } int sum( int numberA, int numberB){ return numberA+numberB; } int div ( int numberA, int numberB){ return numberA/numberB; } |
sum和div这两个函数是为求和和取余的时候调用的,我们看下简单的C#代码:
1 2 3 4 5 6 7 8 9 | static void Main(string[] args) { Console.WriteLine( "sum求和:{0}" , sum(100, 200)); Console.ReadKey(); } static int sum( int a, int b) { return a + b; } |
极其相似的风格,不过上面的那段C程序在VS中是不会报错的,不过在标准的C语言编译器上是会报错的,因为默认情况下程序从上往下执行后面的定义的函数可以调用前面定义的函数;其实上面的那段C程序,应该提前定义sum,div,两种定义的写法,可以不需要参数比如说sum;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #include<stdio.h> int sum( int , int ); int div ( int numberA, int numberB); void main(){ printf ( "sum相加%d\n" ,sum(100,200)); printf ( "div求余%d" , div (300,100)); getchar (); } int sum( int numberA, int numberB){ return numberA+numberB; } int div ( int numberA, int numberB){ return numberA/numberB; } |
上面的代码如果按照面向对象的思想来看需要封装,正常逻辑会想着将最上面的函数声明,和最下面的函数实现给封装,事实上C语言也确实就是这么解决问题的,给出的解决方案是添加一个.h文件和.c文件;我们先来看下实现,然后具体的讲下实现的过程,分别定义一个Calculate.h和Calculate.c文件;
Calculate.h中代码:
1 2 | int sum( int , int ); int div ( int numberA, int numberB); |
Calculate.c中代码:
1 2 3 4 5 6 | int sum( int numberA, int numberB){ return numberA+numberB; } int div ( int numberA, int numberB){ return numberA/numberB; } |
主函数调用:
1 2 3 4 5 6 7 | #include<stdio.h> #include"Calculate.h" void main(){ printf ( "sum相加%d\n" ,sum(100,200)); printf ( "div求余%d" , div (300,100)); getchar (); } |
一般来说编译器编译C语言的几个阶段:
①预处理编译阶段,读取c源程序,对其中的伪指令(以#开头的指令如#include #define)和特殊符号进行处理。扫描源代码,对其进行初步的转换,产生新的源代码提供给编译器。预处理过程先于编译器对源代码进行处理。
②语法和词法分析阶段,这个阶段的工作会判断基本的数据类型定义是不是存在问题,调用的函数是否存在诸如此类的工作;
③编译阶段,首先将C文件编译成成纯汇编语句,然后将将汇编语句转换成跟CPU相关的二进制码,生成各个目标文件 (.obj文件);
④链接阶段,将各个目标文件中的各段代码进行绝对地址定位,生成跟特定平台相关的可执行文件,也可以用objcopy生成纯二进制码去掉了文件格式信息,生成.exe文件;
在vs项目的bin目录下是可以看到生成的Demo.obj和Calculate.obj文件的,这个时候回头看下include其实就是预先定义了sum和div函数,include可以理解将Calculate.h中的代码拷贝到Demo.c文件中,那么如果我们直接include Calculate.c文件会如何呢,因为存在Calculate.obj,那么在链接的过程会报错,具有重复的标识符,至于为什么要分开写要封装,以各位面向对象的思想就不用多说了,最后看下目录和obj吧:
obj文件:
出处:http://www.cnblogs.com/xiaofeixiang
说明:博客经个人辛苦努力所得,如有转载会特别申明,博客不求技惊四座,但求与有缘人分享个人学习知识,生活学习提高之用,博客所有权归本人和博客园所有,如有转载请在显著位置给出博文链接和作者姓名,否则本人将付诸法律。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· [AI/GPT/综述] AI Agent的设计模式综述