C语言组成

C语言组成

一、C语言写工程、项目

​ 一个项目会由多个模块组成,每个模块之间是相对独立,每个模块是由0个或多个**.c.h**组成,各个模块之间可以分开编码研发。

​ 如果继续一个**.c文件去编写,各个模块之间不能分开编码研发—>需要分为多个.c**

​ 一般来说哦,每写一个**.c文件对应写一个.h**文件

.c文件里面写的是实现某个模块里的函数

.h里面写**.c**文件中函数的声明、类型声明……声明语句

​ 如果A模块想用B模块的函数,就需要包含B模块的一个**.h**文件。

二、.c文件组成

​ 一般来说,由以下部分组成

	#### (1)头文件包含部分 ####

​ #include<xxxxxx.h>

​ #include"xxxxxx.h"

#include是把该.h文件/头文件的内容复制粘贴过来

什么时候拿过来?预处理时赋值(编译过程的一个小步骤)

<> 与 " "区别:

​ include 包含头文件时,只给定了头文件的名字;没有给位置

​ 编译器会有一个默认的查找路径:/usr/include

​ <> 就是去默认路径找;

​ " " 先在当前路径找,找不到文件,再去默认的路径下找

所以,一般如果是系统头文件 就用< >;包含自己写的头文件用这个" "

(2)宏定义部分

​ 定义了一个“宏”,宏是用来替换其他内容的东西,一旦定义好了就不能修改

​ a.不带参数的宏:

​ 定义语法:

​ <u>#define 宏名(标识符,不能为关键字) 表达式

如:#define PI 3.14

​ PI是个宏,在程序后面的每一个地方,只要出现PI的地方,都替换成3.14

​ 什么时候替换?

预处理时进行替换(编译过程的一个小步骤)

gcc -E xxxx.c xxxx.i (预处理的命令)

在预处理时,代码里面只要有PI都会用3.14替换

​ 优势:

可读性强,见名知义

可维护性强,比如项目中要用到圆周率,但是突然需要改变精度,需要多位小数,如果直接换,需要修改多次且有可能把需要的数据也给改掉。有宏的话,只需要改一个地方就好了。

​ b.带参数的宏

​ 定义语法:

#define 宏名(参数) 表达式

建议表达式打括号,并且参数也打括号

​ 如:#define MAX(a,b) a>b?a:b

​ int m = MAX(a,b);

​ 替换后 :int m = a>b?a:b;

m = MAX(a&3,b);

		<u>---->  	 m = a&(3>b)?a&3:b</u>     

不会自动加括号,单纯替换,所以写宏的时候参数给打1括号

所以写宏的时候给参数打括号

#define MAX ((a),(b)) (a) > (b)?(a):(b)**

​ 总结:

宏定义在预处理进行替换,不会进行语法检测,也不会增加其他内容比如括号

建议打括号,并且参数也打括号

​ 宏和函数有什么区别

​ (1)函数在运行才会执行、宏是预处理时替换

​ (2)函数在执行时会有额外的开销:会为形参分配内存、现场保护和现场恢复、……

			宏没有额外开销,效率高

​ 为什么不把函数全换为宏

不好,函数可读性更高;

宏只实现简单的功能。

(3)声明部分

​ C语言中声明是指把一个标识符/符号与 一个对象关联起来

a.外部变量的声明:

​ 语法:

​ extern 变量类型 变量名;

​ 比如:

​ 1.c有个重要的全局变量 int a = 10;

​ 在2.c中需要用到它,只需要在2.c中进行一个声明 extern int a;

​ 作用:告诉编辑器,变量a不是本文件中定义的,是在本项目或工程其他文件定义的。如果不想其他文件使用的话,就用static修饰。

b.外部函数的声明:(基本不用,一般写在头文件内)

		1.c:
		int max(int a,int b)
		{
			if(a > b)
				return a;
			else
				return b;
		}
		2.c要用这个函数
			extern int max(int a,int b);

c.类型的声明

		struct xxx{
			类型 变量名;
			……
		};
		类型的声明一般也是放在头文件内,其他文件想使用,就包含该头文件。
		写在.c内,表示只有当前文件可以使用这个类型

d.全局变量的定义及函数的实现

​ 条件编译

​ 1、有选择的编译

		#if 表达式
			代码块1
		# else
			代码块2
		#endif
		 如果表达式的值为真,就会编译 代码块1,不会就编译 代码块2
       	    表达式的值为假,就会编译 代码块2,不会就编译 代码块1
       不会编译:相当于给注释

​ 2、

		#ifdef 宏名
				代码块
		#endif
		如果“宏名”之前定义了的话,才会编译代码块,否则不会编译

​ 3、

		#ifndef  宏名 
				代码块
		#endif
	如:
		#ifndef __TEST_H__
		#define __TEST_H__
		如果“宏名”之前没定义了的话,才会编译代码块,否则不会编译
但是注意一点,不管是 ifdef 还是 ifndef 只会判断宏名有没有 不管 宏 是什么,与宏无关

三、.h文件组成

​ .h 文件中 写声明语句:函数的声明,类型的说明……

​ 一般来说 一个.c 对应一个.h ,这个.h 文件中的函数(包括注释),以及需要用到的类型

​ 注释: 至少要有以下几点:

​ 函数功能

​ 函数参数的意思

​ 函数返回值

​ 函数的“坑”

为了解决头文件被一个.c 文件重复/多次 包含而产生的错误,

使用 条件编译 来处理,

效果: 无论包含几次,都跟包含一次效果一样

一个项目中无论有多少个 .c 和 .h ,main函数有且仅有一个。

编译时需要把项目中所有的.c文件包含: gcc xxx1.c xxx2.c … -o

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值