目录
1程序的翻译与执行
2预定义符号
3#define
(1)#define 定义标识符
(2)#define定义宏
(3)#define替换规则
(4)#和##
(5)带副作用宏参数
(6)宏和函数对比
4命令定义
5预处理指令#include
6预处理指令#undef
7条件编译
8文件包含(include)
9其他
10最后
1程序的翻译与执行
(1)
- 组成一个程序的每一个源文件通过编译过程分别转换成目标代码。
- 每一个目标文件由链接器捆绑在一起,形成一个单一而完整的可执行程序。
- 链接器同时也会引入标准c函数库中任何被程序所用到的函数,而且它可以搜索程序员个人的程序库,将其需要的函数也链接到程序中。
(2)
(3)
(4)
程序执行过程:
程序必须载入内存中。在有操作系统的环境中:一般由操作系统完成。独立环境中,程序载入必须手工安排,也可能通过可执行代码置入只读内存来完成。
程序的执行便开始。便调用main()函数。
开始执行程序代码。这个时候程序将使用一个运行时堆栈(stack),存储函数的局部变量和返回地址。程序同时也可以使用静态(static)内存,存储于静态内存中的变量在程序的整个执行过程一直保留他们的值。
终止程序。正常结束main()函数;也有可能是意外终止。
2预定义符号
(1)预定义符号
- __FILE__ //进行编译的源文件
- __LINF__ //文件当前的行号
- __DATE__ //文件被编译的日期
- __TIME__ //文件被编译的时间
- __STDC__ //如果编译器遵循ANST C,其值为1,否则未定义。
都是内置的
printf("file:%s line:%dn",__FILE__,__LINE__);
3#define
(1)#define 定义标识符
语法:
- #define name stuff
#define MAX 1000 #define reg register //换短名字 #define do_forever for(;;) //更形象符号代替实现 #define CASE break;case //在写case语句的时候自动带上break //后面stuff太长可以用换行写
(2)#define定义宏
- #define机制包括一个规定,允许把参数替换到文本中,这种实现称为宏或定义宏
定义方式 :
- #define name(parament-list)stuff,其中parament-list是由逗号隔开的符号表,他们可能出现在stuff中。
- 左边括号与name相邻
#define SQUARE(x) x*x SQUARE(s); //预处理器就会替换上面表达式: //s*s
例:
#include#define SQUARE(x) x*x int main() { int ret = SQUARE(5 + 1); printf("%dn", ret); return 0; }
结果:11
==》定义宏时,他说进行替换,并不是进行传参,所以多添加():#define SQUARE(x) ((x)*(x))
(3)#define替换规则
几个步骤:
- 在调用宏时,首先对参数进行检查,看看是否包含任何由#define定义的符号,它们先替换
- 替换文本随后插入到程序原来文本的位置。宏,参数名被他们的值替换
- 最后再次对结果文本扫描,查看是否包含#define定义的字符,有,重复上述过程
另
- 宏不能递归。
- 字符串常量的内容并不被搜索
(4)#和##
#:
如何把参数插入到字符串?
#include#define PRINT(x) printf("the value of "#x" is %dn",x) int main() { int a = 10; int b = 20; PRINT(a); PRINT(b); return 0; }
##:
- 作用:可以把位于它两边的符号合成一个符号。它允许宏定义从分离的文本段创建标识符
#include#define CAT(x,y) x##y int main() { int ssyf = 2021; printf("%dn", CAT(ss, yf)); }
- 有点像合成
(5)带副作用宏参数
使用带有副作用的参数,结果有时会超出预料
如:
- x+1//不带副作用
- x++//带有副作用
(6)宏和函数对比
宏的优势
- 宏比函数在程序大小的规模和速度方面更好
- 宏是类型无关的(宏可以出现类型)
宏的劣势
- 宏插入程序中时,除非宏较小,否则可能大幅度增加宏的长度。编译时
- 宏是没法调试的,因为出错都是出现在编译后
- 宏是类型无关的,也就不够严谨
- 宏可能带来运算优先级问题
4命令定义
宏和函数很相似==》宏名全部大写,函数名不全大写
5预处理指令#include
可以使另一个文件被编译。
预处理器像删除这条指令,并用包含文件的内容替换。(一个文件被包含10次,就被编译10次)
6预处理指令#undef
这指令用于移除一个宏定义
7条件编译
(1)
方便在编译一个程序时将一条语句(一组语句)编译或者放弃。
- 调试性的代码,删除可惜,保留又碍事,可选择性的编译
#include#define __DEBUG__//如果未定义,那么下边①不会被执行 int main() { int i = 0; int arr[10] = { 0 }; for (i = 0;i < 10;i++) { arr[i] = 0; #ifdef __DEBUG__ printf("%dn", arr[i]);//①观察数组是否被赋值成功。 #endif } return 0; }
(2)
①
#if 常量表达式
//...
#endif
②判断是否被定义
#if defined(symbol)
#ifdef symbol
8文件包含(include)
(1)头文件被包含的方式:
本地文件被包含
- #include”filename“
先在源文件所在目录下查找,如果头文件未找到,编译器就像查找库函数一样在标准位置查找文件。如果找不到就报错。
vs下,按自己按照路径查找
库文件包含
- #include
查找头文件自己去标准路径下查找,找不带就提示错误。
如果发生嵌套文件包含:
避免文件重复编译,选择条件编译
每个头文件的开头写:
- #ifndef __TEXT_H__
- #define __TEXT_H__
- //头文件内容
- #endif //__TEXT_H__
或者
- #pragma once
9其他
(1)命令行定义
c的编译器,允许在命令行定义符号。
如:当我们根据同一个源文件要编译出不同的一个程序的不同版本的时候,即可以使用。
(2)
#error
#pragma
#line
10最后
仅作学习使用,笔记并不全
参考:
c语言编程 C语言入门 c语言(C语言程序设计教程 c语言视频教程 c语言零基础入门教程 学习c语言 c语言视频教程 c语音 C语言教程 C语言编程项目 C语言_哔哩哔哩_bilibili



