#include <stdio.h>
hello.c
gcc hello.c //编译
预处理 (预编译)
汇编 (汇编语言) ---助记符
编程:
人类语言 --->编程语言(C语言)---汇编语言--->机器语言(01010)
八位的单片机 0101 0101 //加法
//0101 0101
16位
32位 0101 0101 0101 0101 0101 0101 0101 0101 //add
64位
main()
{
int a = 1;
int b = 2;
printf("hello world! %d \n",a+b);
}
a.out //
-----------------------------------
编译过程:
预处理
编译
汇编
链接
预处理:
1.宏定义
2.文件包含
3.条件编译
1.宏定义 --- 定义了符号常量
#define 标识符 字符串
#define 宏名 宏值
#define N 100
表示,定义了一个宏 (符号),而这个符号 代表的值 就是100
#define 宏名(参数) 宏值
说明:
1. 预处理阶段,只做文本原样替换
2. 宏 就是用 宏值 将 宏名 原样替换
3. 用途
当作常量来用
好处,可以做到 一改全改,方便操作
4. 宏名
符合标识符命名规则
宏名,一般都是大写 --- 主要是为了和普通变量名区分
5. 程序中 处于 ""中的 宏名 不会被替换
6. 宏名 不要和关键字重名
7. 宏替换过程中,存在宏的副作用 ---- 文本的原样替换
处理:
能加括号的尽量都加括号
8. 宏定义 只能放在一行
练习:
从键盘输入 圆的半径,求出圆的周长和面积
L = 2 * π * r
S = π * r * r
π 常量
#define PI
练习:
用带参宏,实现找两个数中的最大值
文件包含
#include "文件名" //首先在当前路径下寻找要包含的文件,找不到再到系统默认路径下寻找
#include <文件名> //默认到系统指定路径下寻找头文件
作用:
将文件名代表的文件中的内容 ,替换到当前文件
条件编译: //也是文本替换 --- 符合条件的文本
//形式1
#ifdef 标识符
程序段1
#else
程序段2
#endif
//形式2
#ifdef 标识符
程序段1
#endif
#ifndef 标识符
程序段1
#else
程序段2
#endif
#if 表达式
程序段1
#else
程序段2
#endif
多文件编程
main.c
|--add.c //自己的点c通常会包含自己的点h
|--add.h //一部分是 对外的函数声明 一部分时自己的点c需要用到的头文件等内容
|--sub.c
|--sub.h
作业:
定义一个字符串 "12345"
要求:
将"12345" 转化数值 12345 输出
写成函数
重要知识点总结
1. 预处理指令的基本概念
-预处理阶段:在编译前执行,处理所有以 `#` 开头的指令。
- 常见指令:`#include`, `#define`, `#ifdef`, `#ifndef`, `#endif`, `#if`, `#else`, `#elif`, `#error`, `#pragma` 等。
2. 宏定义(`#define`)
(1) 无参宏
- 简单替换:`#define PI 3.14`,预处理时直接替换为值。
- 注意事项:
- 避免在宏末尾加分号,可能导致语法错误。
- 若替换内容是表达式,需加括号确保优先级正确:
```c
#define SQUARE(x) ((x) * (x)) // 正确
#define SQUARE(x) x * x // 错误:可能导致运算顺序问题
(2) 带参宏
- 参数替换:`#define MAX(a, b) ((a) > (b) ? (a) : (b))`
- 副作用问题:
- 参数可能是表达式(如自增操作),导致多次求值:
```c
int a = 5, b = 10;
int max = MAX(a++, b); // 展开后:((a++) > (b) ? (a++) : (b)) → a被递增两次
```
---
3. 条件编译
- 用途:根据条件选择性地编译代码块。
- 常见指令:
- `#ifdef` / `#ifndef`:检查宏是否已定义。
```c
#ifdef DEBUG
printf("Debug mode");
#endif
```
- `#if`:根据常量表达式判断:
```c
#if (VERSION >= 2)
// 编译新功能
#elif (VERSION == 1)
// 旧功能
#else
#error "Unsupported version"
#endif
```
- 防止头文件重复包含:
```c
#ifndef MY_HEADER_H
#define MY_HEADER_H
// 头文件内容
#endif
```
---
4. 文件包含(`#include`)
- 两种形式:
- `#include <stdio.h>`:系统头文件,按标准路径查找。
- `#include "myheader.h"`:用户自定义头文件,优先从当前目录查找。
- 嵌套包含问题:避免循环依赖,合理使用条件编译。
---
5. 预定义宏
- 常用内置宏:
- `__LINE__`:当前行号。
- `__FILE__`:当前文件名。
- `__DATE__`:编译日期(如 "Jan 23 2023")。
- `__TIME__`:编译时间(如 "12:34:56")。
- `__func__`:当前函数名(C99)。
---6. 预处理操作符
- `#` 运算符:将宏参数转换为字符串。
```c
#define STR(s) #s
printf("%s", STR(Hello)); // 输出 "Hello"
```
- `##` 运算符:拼接符号。
```c
#define CONCAT(a, b) a##b
int var12 = 100;
printf("%d", CONCAT(var, 12)); // 输出 100
```
---
7. 错误与警告指令
- #error`:强制终止编译并输出错误信息。
```c
#ifndef C_VERSION
#error "C99 compiler required"
#endif
```
- #warning`(非标准):生成编译警告(部分编译器支持)。
---
8. 其他指令
- #line`:修改编译器报告的行号和文件名。
```c
#line 100 "new_file.c" // 后续代码的行号从100开始
```
- `#pragma`:编译器特定指令(如优化、对齐)。
```c
#pragma pack(1) // 设置结构体按1字节对齐
```
9. 可变参数宏(C99)
- 使用 `__VA_ARGS__` 处理可变参数:
```c
#define LOG(fmt, ...) printf(fmt, __VA_ARGS__)
LOG("Value
C语言预处理及进阶技巧
7958

被折叠的 条评论
为什么被折叠?



