c语言宏定义在预处理阶段,预处理和宏定义
8种机械键盘轴体对比
本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选?
宏定义
基本概念预处理部分: #include #define 放在函数之外,一般都放在源文档的前面
预处理由预处理进程负责,当对一个源文档进行编译时,系统将自动引用预处理进程对源进程中的预处理部分作处理,处理完毕将自动进入对源进程的编译。
C语言提供了多种预处理功能,如宏定义、文档包含、条件编译等。
不带参数的宏定义被定义为 宏 的标识符称为 宏名。 在编译阶段对进程中所有出现的 宏名 都用宏定义中的字符串去代换
宏定义由源进程中的宏定义命令完成的。宏代换是由预处理进程自动完成的。
c语言中 宏分为 有参数 和无参数两种。1
2
3
4
5
6
7#define 标识符 字符串
以 # 开头的均为预处理命令
define 为预处理命令
标识符 为所定义的宏名
字符串 可以是常数、表达式、格式串等
宏使用时的注意事项习惯上宏名用大写字母表示,以便于与变量区别,但是也允许使用小写字母
宏定义是用宏名表示一个字符串(可以是任何字符,常数,表达式),在宏展开时又以该字符串取代宏名。
预处理进程不做检查,在宏展开编译的时候发现
宏定义不是说明或语句,末尾不用加 分号“;” 加“;” 连同“;”一起置换
宏定义必须写在函数之外,默认的有效区到源进程结束, 要是提前结束 使用 #undef 命令1
2#undef PI
宏名在源进程中使用双引号括起来,则预处理进程不对其作宏代换1
2
3
4
5
6
7#define H "hello world"
int main(){
printf(H);
printf("n%sn",H);
printf("Hn"); // H
}
宏定义允许嵌套,在宏展开时由预处理进程层层代换1
2
3#define PI 3.1415926
#define R 5
#define SUM 2*PI*R
可用宏定义表示数据类型,使书写方便
对输出格式做宏定义,减少书写麻烦
#define 和 typedef的区别注意用宏定义表示数据类型和用typedef定义数据说明符的区别。宏定义只是简单的字符串代换,是在预处理完成的,而typedef是在编译时处理的,不是作简单的代换,而是对类型说明符重新命名,被命名的标识符具有类型定义说明的功能。1
2
3
4
5
6
7
8
9
10#define PIN1 int *
typedef int * PIN2;
PIN1 a,b
a = &m; // OK int *a; a = &m;
b = &n; // ERROE int b; b = &n;
PIN2 c,d;
c = &m; // OK int *c; c = &m;
d = &n; // OK int *d; d = &n;
带有参数的宏定义有参宏的定义方法
C语言中允许带有参数,在宏定义中的参数成为形式参数,在宏调用中的参数称为实际参数。
对带参数的宏,在调用中,不仅要宏展开,而且要用实参去代换形参。1
2
3
4
5
6
7
8
9
10
11// 带参数的宏定义的一般形式为:
#define 宏名(形参表) 字符串
// 带参宏调用的一般形式为:
宏名(实参表)
eg:
// 宏定义
#define M(y) y*y+3*y
// 宏调用
M(5);
有参宏的注意事项带参宏定义中,形参之间可以出现空格,但是宏名和形参表之间不能有空格出现。
带参宏定义中,形参不分配内存单元,实参有具体值,必须作类型说明,带参宏定义只是符号代换,不存在值传递。而函数中形参和实参是两个不同的量,有各自的作用域,调用时进行 值传递
在宏定义中形参是标识符,而宏调用中的实参可以是表达式
在宏定义中,字符串中的形参通常要用括号括起来避免出错。
宏定义可以用来定义多个语句。在宏调用时,把这些语句又代换到源进程内。
条件编译
为什么要用条件编译?按不同条件去编译不同的进程部分,因而产生不同的目标代码文档。有利于进程的移植和调试。
可以使用条件语句来实现条件编译。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28// 第一种形式
#if 常量表达式
进程段1
#elif
进程段2
#else
进程段3
#endif
条件编译后面的表达式中不能出现变量,只能识别常量和宏定义
// 第二种形式
#ifdef 标识符
进程段1
#else
进程段2
#elseif
// 如果标识符已被#define命令定义过则对进程段1进行编译;否则对进程段2进行编译。
// 第三种形式
#ifndef 标识符
进程段1
#else
进程段2
#endif
// 如果标识符未被 #define 命令定义, 则对进程段1进行编译,否则对进程段2进行编译。
预处理
什么是预处理?以 # 开头的代码行
#号必须是该行除了任何空白字符外的第一个字符。
#后是命令关键字,在关键字和#号之间允许存在任意个数的空白字符。
整行语句构成了一条预处理命令,该命令将在编译器进行编译之前对源代码做某些转换
常见的预处理命令命令说明#空命令,无任何效果
#include包含一个源代码文档
#define定义宏
#undef取消已定义的宏
#if如果给定条件为真,编译下面的代码
#ifdef如果宏已经定义,编译下面的代码
#ifndef如果宏没有定义,编译下面的代码
#elif#if不为真,当前条件为真,编译下面的代码
#endif结束条件编译块
static和extern的使用它们都是用来修饰变量(局部的static实际也是全局)
static修饰的变量 只有你的包含那个变量定义的源代码文档可以访问
extern定义的变量 是任何一个源文档都可以访问,只要声明了就可以
static与extern对局部变量的作用static对局部变量的作用延长局部变量的生命周期,从进程启动到进程退出,但是它没有改变 变量的 作用域
定义变量的代码在整个进程运行期间仅仅会执行一次1
2
3
4
5
6
7
8
9
10
11
12
13
14void add(){
static int a = 10; // int a = 10;
a++;
printf("a++: %dn",a);
}
int main() {
add(); // 11
add(); // 12
add(); // 13
return 0;
}
// extern 不是定义局部变量,它是在函数内部声明的全局变量
static与extern对全局变量的作用全局变量内部变量:只能在本文档中访问的变量
外部变量:可以在其他中访问的变量,默认所有全局变量都是外部变量static作用声明一个内部变量
定义一个内部变量
注意:在不同文档中可以定义同名的内部变量如果声明的时候没有写extern那系统会自动定义这个变量,并将其初始化为0
如果你使用extern来声明一个变量,如果没有你定义的,那么系统就会报错
static与extern对函数的作用内部函数: 在A文档中定义的函数,在A文档中访问
外部函数: 在B文档中访问A文档中定义的函数,函数在B中称之为外部函数
全局变量&局部变量常见问题
局部变量能否和全局变量重名?能,局部会屏蔽全局,要用全局变量,需要使用”::”(域运算符)
如何引用一个已经定义过的全局变量?extern, 可以用引用头文档的方式,也可以用extern关键字,使用引入头文档方式(有错误会在编译阶段报错),使用extern方式引用时(有错误会在连接期间报错)
全局变量可以定义在被多个.c文档包含的头文档中?可以,在不同的C文档中以static形式来声明同名全局变量
static全局变量和普通的全局变量区别static全局变量只初始化一次,防止在其他文档单元中被引用.
static局部变量和普通的局部变量区别static局部变量只被初始化一次,下一次依据上一次的结果值.
static函数和普通函数区别static函数在内存中只有一份,普通函数在每个被调用中维持一份拷贝.
进程的局部变量存在于(堆栈)中,全局变量存在于(静态区)中,动态申请数据存在于(堆)中
c语言宏定义在预处理阶段,预处理和宏定义相关推荐
- 利用宏定义在编译阶段检查结构体大小的方法
http://blog.csdn.net/crazycoder8848/article/details/8292770 ======================================== ...
- 【C 语言】编译过程 分析 ( 预处理 | 编译 | 汇编 | 链接 | 宏定义 | 条件编译 | 编译器指示字 )
相关文章链接 : 1.[嵌入式开发]C语言 指针数组 多维数组 2.[嵌入式开发]C语言 命令行参数 函数指针 gdb调试 3.[嵌入式开发]C语言 结构体相关 的 函数 指针 数组 4.[嵌入式开发 ...
- C语言条件编译及编译预处理阶段
一.C语言由源代码生成的各阶段如下: C源程序->编译预处理->编译->优化程序->汇编程序->链接程序->可执行文件 其中 编译预处理阶段,读取c源程序,对其中的 ...
- C语言之预处理探究(一):宏
相关博文:C语言之预处理探究(四):#.##和预定义宏 相关博文:C语言之预处理探究(三):头文件包含 相关博文:C语言之预处理探究(二):条件编译(Condition Compile) 一. 发生时 ...
- C语言程序设计 | 程序环境和预处理:翻译环境和执行环境、宏、条件编译
程序环境和预处理: 翻译环境和执行环境 宏 条件编译 翻译环境和执行环境 在ANSI C的任何一种实现中,存在两种不同的环境. 第一种是翻译环境,在这个环境中源代码被转换成可执行的机器指令.第二种是执 ...
- C语言之程序环境和预处理
重点 程序的翻译环境 程序的执行环境 详解:C语言程序的编译+链接 预定义符号介绍 预处理指令 #define 宏和函数的对比 预处理操作符#和##的介绍 命令定义 预处理指令 #include 预处 ...
- c语言预处理命令12个,C语言编译预处理和预处理命令
1.预处理概念:编译程序时,编译器将对程序文件作至少两个阶段的编译预处理,预处理程序预处理阶段和编译程序预处理阶段. 预处理程序预处理阶段:C预处理程序先于C编译程序运行.预处理程序从前向后根据预处理 ...
- bilibiliclass76-80_C语言_程序的编译(预处理操作)+链接
程序环境和预处理 本章重点: 程序的翻译环境 程序的执行环境 详解:C语言程序的编译+链接 预定义符号介绍 预处理指令 #define 宏和函数的对比 预处理操作符#和##的介绍 命令定义 预处理指令 ...
- [C/C++]C语言的程序环境和预处理
本文主要讲述C语言的程序环境和预处理. 一.程序的翻译环境和执行环境 存在源代码转换为可执行的机器指令的翻译环境和实际执行代码的执行环境,两个不同的环境. 1.翻译环境 每个源文件通过编译 ...
最新文章
- 网络通信基础:ICMP基础通识
- C/S框架-WebService部署图
- 计算机安全知识课堂导入设计,“计算机安全与防护教学设计”教学设计.doc
- C++小型公司管理系统
- java连接mysql数据库C3P0入门
- 吴思涵国内首场肿瘤ecDNA学术报告|深度揭秘半个世纪ecDNA的研究成果及突破性进展...
- 解决方案:重复抢单(Redis原子计数器incr)
- Theano 中文文档 0.9 - 5.2 Mac OS安装说明
- 常见30种数学建模模型_11.12|认识数学模型与数学建模许可
- bzoj4695 最假女选手(势能线段树/吉司机线段树)题解
- QI精小无线充电接收模块(带线圈)可以输出5V,4.2V,QI协议,22MM圆形,500MA电流拿了即可使用
- wps实现项目编号转成文本形式
- 今日头条算法及技术架构分析
- java 生成ppt_Java 创建并应用PPT幻灯片母版
- 新元宇宙奇科幻小说原创作品每周连载《地球人奇游天球记》第九回女神伴飞
- C++ 标准库の使用迷思
- 【区块链 | Solidity】以太坊Solidity如何实现海量空投代币?
- 春天正是补气的好时刻,喝枸杞+黄芪就对了
- Tomcat与JDK版本的对应
- 计算机教学设计与反思,[信客教案及反思] 信息技术教案课后反思
热门文章
- 一次Ajax报错:“存储空间不足,无法完成此操作”的解决经验
- ImageView 加载本地(手机)图片
- 大数据第三季--Hive(day3)-徐培成-专题视频课程
- 性能测试工程师面试一定会问的14个面试题型
- 运动无线耳机哪款不容易掉、最不容易脱落的蓝牙耳机推荐
- git 删除git管理_使用Git管理多媒体文件
- apidoc 自动化生成 api接口文档
- 巴巴腾机器人视频_巴巴腾机器人,没想到你是这样的机器人!
- 拯救者R7000ubuntu18.04解决分屏问题(NVIDIA显卡驱动安装)
- html怎么让页脚下方的空白页,Word中后面多出来带页眉页脚的空白页怎么删除