宏观控制_C语言快速入门与计算机二级备考
全局变量
全局变量
-
变量可以定义在函数外,使之区别于函数一节中的本地变量,称全局变量
-
全局变量具有全局的生存期与使用域,它们与任何函数无关,在任何函数内都可使用
对全局变量的访问与操作,将无视函数域,直接作用到其身上
-
初始化:没有初始化的全局变量默认为0,指针默认指NULL(本地变量则不会有默认值)
只能用编译时已知的值来初始化全局变量(不能用变量为全局变量赋值)
-
如果函数内部有与全局变量同名的变量,则全局变量会被暂时隐藏,只对本地变量操作
静态本地变量
-
创建静态本地变量:本地变量定义时加上
static
前缀修饰符 -
在函数离开时,一般的本地变量生存期结束而消亡,但静态本地变量会继续存在并保存其值
静态本地变量的初始化只会在第一次进入函数时进行,以后再进入函数会保持上次离开时的值
-
静态本地变量实际上是特殊的全局变量:其与全局变量一样有全局的生存期,但作用域只在函数内
全局变量的应用
-
对于返回指针的函数:
返回一个本地变量的指针是危险的,因为一旦离开这个函数本地变量就消亡了,其地址会被分配给别的变量使用
因此,返回一个全局变量/静态本地变量的地址是安全的
返回在函数内的malloc的内存是安全的,但容易造成问题,最好的做法是返回传入的指针
-
不要使用全局变量在函数间传递参数与结果
甚至于尽量避免使用全局变量,使用全局变量和静态本地变量的函数是线程不安全的
宏
定义宏
-
#
开头的是编译预处理指令它们并非C语言的一部分,其它语言也可以使用
-
#define 名字 值
用于定义一个宏名字必须是一个单词,一般用大写以区分变量,但并非规定
值可以是任何东西,不受数据类型限制(注释除外)
结尾没有分号(因为不是C的语句)
例如:
#difine PI 3.1415
这样就将PI定义为了3.1415在编译时会预处理将程序中所有的PI替换为3.1415,这种替换是完全的文本替换
-
如果一个宏的值中有其它宏的名字,也会被替换
如果一个宏的值超过一行,最后一行之前的行末需要加\
特殊的宏
-
没有值的宏:
#define _DEBUG
这类宏用于条件编译,后面有其它的编译预处理指令来检查这个宏是否被定义过了(如果存在则编译一部分代码,不存在就编译另一部分)
-
已经被预定义的宏,在程序中可以直接使用
__LINE__
源代码文件的行号__FILE__
源代码文件的文件名(从根目录开始)__DATE__
__TIME__
编译时的文件名__STDC__
判断当前程序文件是不是标志C文件(若遵守ANSIC标准时为1)
带参数的宏
-
宏可以带参数,类似于调用函数
-
例如:
#define cube(x) ((x)*(x)*(x))
在使用时,
cube(5)
将等于5×5×5,也可以在括号中使用变量,运算式 -
注意:替换是文本替换,于是使用运算式作参数时运算顺序可能与预期不同
原则:定义时一切都要有括号:整个值与每次参数出现都要括号
-
宏可以带多个参数,例如:
#define MIN(a,b) ((a)>(b)?(b):(a))
-
宏可以嵌套其它宏
多个源代码文件
-
如果
main()
里面的代码太长,拆分为多个函数同理,一个源代码文件太长,拆分为几个文件
-
直接将不同函数放到不同的.c文件是无法编译的
-
使用多个源文件代码需要用到项目:
- 在编译器中创建新项目
- 在项目中添加所需的.c代码文件
- 注意,有时编译器有分开的编译与构建选项,前者对单个源代码文件编译,后者链接整个项目
-
一个.c文件是一个编译单元,编译器每次编译只处理一个编译单元
头文件
-
当不同函数拆分到不同.c文件后,倘若在编译一个函数时,没有对其中另一个函数的声明,编译器将猜测这另一个函数的参数类型为int
这样极易在数据类型不同时出错
-
因此,需要一个中间媒介来存放函数原型,以便编译器得知函数原型
这个文件就是头文件(.h文件)
-
在需要调用某个函数时,将这个函数的函数原型放到一个头文件中
这个头文件同其它代码文件一样放到项目当中
在需要调用这个函数的源代码.c文件中
#include “这个头文件.h”
在这个函数本身的代码中也要放这个头文件
-
#include
是一个编译预处理指令,和宏一样,在编译之前处理它的作用是将所
include
的文件的全部文本插入它所在的地方-
#include
后的' '
与< >
表示了这个指令指出插入文件的两种形式" "
先到当前目录(.c所在目录)里寻找,如果没有再去编译器指定目录< >
只在指定目录(编译器知道自己的标准库的头文件)
但
#include
本身不用来引入库,它只是让编译器知道函数原型,例如stdio.h
文件中只有printf
的原型,实际的代码在别处 -
-
一般的做法是:任何.c文件都有对应的同名.h文件,将所有对外公开的函数原型和全局变量声明放入
-
不对外公开的函数:在函数/全局变量前加
static
使得其只在所在的编译单元(.c文件中)中被使用
声明
-
在项目某处定义一个全局变量,在另一文件中想使用它
-
在头文件中,使用前缀
extern
便可声明一个全局变量,例如//在某个.C文件中定义了一个全局变量: int gAll = 12; //在另一个.C文件中想使用它,则在头文件里写入: extern int gAll; //这样就向编译器声明了一个全局变量
-
由此我们可知,C中的定义与声明是两码事:
定义产生代码,分配内存,告诉编译器函数的具体作用或变量的值;如:函数 / 全局变量
声明不产生代码,只用于告诉编译器变量名称和类型;如:函数原型/变量/结构/宏/枚举/类型等的声明 /
inline
函数 -
关于头文件与声明:一般只有声明(各个函数原型与对全局变量的声明)可以放入头文件
否则会导致一个项目多个编译单元中出现重名实体
-
为了规避上述问题,利用条件编译和宏,引入标准头文件结构:
#ifndef __头文件名_H__ //如果没有定义过头文件这个宏 #define __头文件名_H__ //就定义这个宏 //头文件内容 #endif //宏的内容到此结束 //如果已经被定义过了,上述内容就不会再被编译了 //由此保证了这个头文件在一个编译单元中只会被#include一次
本文来自博客园,作者:无术师,转载请注明原文链接:https://www.cnblogs.com/untit1ed/p/18547882
本文使用知识共享4.0协议许可 CC BY-NC-SA 4.0
请注意: 特别说明版权归属的文章以及不归属于本人的转载内容(如引用的文章与图片)除外
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了