博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C语言-函数
阅读量:6704 次
发布时间:2019-06-25

本文共 2352 字,大约阅读时间需要 7 分钟。

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文件:

本文转自Fly_Elephant博客园博客,原文链接:http://www.cnblogs.com/xiaofeixiang/p/4202502.html,如需转载请自行联系原作者

你可能感兴趣的文章
Oracle内置函数nvl ,trunc
查看>>
Predicate 学习
查看>>
(笔记)电路设计(三)之0欧姆电阻、磁珠、电感的应用
查看>>
身份证合法性判定
查看>>
Scanner
查看>>
myeclipse下dwr.xml配置文件没有自动提示解决办法
查看>>
STL库
查看>>
2011-04-13 15:54 利用事件触发实现ActiveX调用js函数
查看>>
IntelliJ IDEA 12 EAP 更新 (122.694)
查看>>
Python发送带附件的Email
查看>>
python代码风格建议
查看>>
MFC对话框编程
查看>>
bat 文件清楚当前目录下的所有目录及文件
查看>>
iOS 关闭键盘
查看>>
设非主键为聚集索引
查看>>
SQL 将一个字段内用逗号分隔的内容分成多条记录
查看>>
lucene 使用教程<转>
查看>>
邮件服务器脱离域灾难恢复
查看>>
关于C++ const 的全面总结
查看>>
IoC容器Autofac(3) - 理解Autofac原理,我实现的部分Autofac功能(附源码)
查看>>