预处理详情
预定义符号C语言设置了一些预定义符号,可以直接使用,预定义符号也是在预处理期间处理的 1234__FILE__ //进行编译的源文件__LINE__ //文件的行号__DATE__ //文件被编译的日期__TIME__ //文件被编译的时间 1printf("%d", __LINE__); #define 定义常量基本语法 1#define name stuff 一般来说宏定义的名称统一为全大写 例如 12// 宏定义是直接替换printf("%d\n", NUM); 编译后实际执行的是 1printf("%d\n", 10); 需要注意的是,用 #define 定义标识符的时候不要加 ; , 因为 #define 在编译时会直接整个替换,这个 ; 也会被替换进去,就会出现语法上的错误,例如 12#define NUM_1 20;printf("%d\n", NUM_1); 编译时实际执行的是 1printf("%d\n", 20;); 如果定义的stuf...
编译与连接
翻译环境和运行环境在 ANSI C的任何一种实现中,存在两个不同环境 第一种是翻译环境,在这个环境中源代码被转换为可执行的机器指令 第二种是运行环境,用于实际执行代码 翻译环境翻译环境是由编译和链接两大过程组成的 编译又可以分解成:预处理、编译、汇编三个过程 一个C语言项目中可能有多个.c文件构成,多个.c文件会单独经过编译器,编译处理生 成对应的目标文件,多个目标文件和链接库一起经过链接器处理生成最终的可执 行程序 在 windows 环境下目标文件后缀为.obj, linux 环境下目标文件后缀为.o 预处理预处理阶段,源文件和头文件会被处理为.i文件 主要处理源文件中 # 开始的预编译指令 将所有 #define 删除,并展开宏定义 处理所有条件编译指令,如:#if、#ifdef、#elif、#else、#endif 处理 #include 预编译指令,将包含的头文件的内容插入到该预编译指令的位置 删除所有注释 添加行号和文件名标识,方便后续编译器生成调试信息 或保留所有的 #pragma 的编译器指令,编译器后续会使用 经过预处理后的.i文件中不再包...
函数栈帧的创建与销毁
寄存器寄存器(Register)是 CPU 内部极高速的存储单元,用于暂存指令、数据和地 址。它的主要作用是减少 CPU 访问内存的次数,从而极大提升程序执行速度。 常见的寄存器有 eax、ebx、ecx、edx、ebp、esp 等 其中 ebp(栈顶指针) 、 esp(栈底指针) 是用于维护函数栈帧的 main 函数也是被调用的本文的所有代码都是在 visual studio 2013 中运行 12345678910111213141516int Add(int x, int y){ int sum = 0; sum = x + y; return sum;}int main(){ int a = 10; int b = 20; int c = 0; c = Add(a, b); printf("%d\n", c); return 0;} 这段代码在进入调试后,可以看到如图所示 main() 函数也是被调用的,main()在 __tmainCRTStartup()函数中被调用,而 __tmainCRTStartu...
C语言文件操作
文件分类在C程序设计中,一般将文件按功能分为程序文件和数据文件 程序文件C程序文件包括源程序文件(后缀为.c),目标文件(windows环境后缀为.obj),可执行文 件(windows环境后缀为.exe) 数据文件文件不一定是程序,而是程序运行时读写的数据,如程序运行需要从中读取数据或写 入数据的文件 二进制文件和文本文件根据数据的组织形式,数据文件被称为文本文件或二进制文件 数据在内存中以二进制的形式存储,如果不加转换的输出到外存的文件中,就是二进 制文件 如果要求在外存上以ASCII码的形式存储,则需要在存储前转换。以ASCII字符的 形式存储的文件就是文本文件 字符一律以 ASCII 码存放,数值型数据既可以用 ASCII 码形式存储,也可以用二进制 存储 文件的打开和关闭流程序的数据需要和外部设备进行频繁的操作,为了方便对各种设备进行方便的操作, 抽象出了流的概念。 简单来说,流是连接程序和外部设备的管道,屏蔽了设备差异,流提供了统一的接口, 程序只需要调用这些接口就可以了 标准流C语言程序启动时,默认打开了三个流: stdin 标准输入流,在大多数的环境中从键盘输...
C语言动态内存管理
动态内存分配在创建变量的时候实际上就是在开辟分配空间 12int val = 0; // 开辟了四个字节的空间int arr[5] = { 0 }; // 在栈空间上开辟了10个字节的连续空间 创建变量的开辟空间方式有两个特点: 空间开辟大小是有限的 数组在声明的时,必须指明数组长度,一旦确定了不能调整 某些情况,需要的空间大小在程序运行时才知道 C语言提供了动态内存开辟,让开发者自行申请和释放空间 malloc 和 freemalloc一个用于动态开辟内存空间的函数,包含在头文件<stdlib.h>中,语法格式如下 1void* malloc (size_t size); 开辟成功,返回一个指向开辟好空间的指针 开辟失败,返回 NULL 返回值类型是 void* , 使用时需操作者根据需求决定怎么使用 size 如果为 0, malloc 的行为是标准未定义的,由编译器决定 123456789101112// 20个字节 放5个整型int* p = (int*)malloc(20);if (!p){ perror...
C语言枚举
一、枚举枚举的意思就是一一列举 1.1 枚举类型的声明1234567enum Color{ // 三原色 , 枚举常量 RED, GREEN, BULE}; 可能取值都是有值的,默认从 0 开始,一次递增1 123printf("%d\n", RED);printf("%d\n", GREEN);printf("%d\n", BULE); 枚举常量可以在声明时赋予初始值,声明后不能再修改 1234567enum Color{ // 三原色 , 枚举常量 RED, GREEN = 5, // 赋值后是也遵循枚举常量值的规则 BULE}; 二、枚举类型的优点 增加代码的可读性和维护性 和 #define 的标识符比较枚举类型有类型检查,更严谨 便于调试,预处理阶段会删除 #define 定义的符号 使用方便,一次可以定义多个常量 枚举常量遵循作用域规则 三、 枚举类型的使用12345678910enum Color{ // 三原色 , 枚举常量 RED...
C语言联合体
联合体和结构体类似,由一个或多个成员构成,这些成员可以是不同的类型 特点是所有成员共用一块内存空间,也叫共用体 给联合体其中一个成员赋值,其他成员的值也会发生变化 联合体的声明12345678union Un{ char a; // 1 int x; // 4};union Un u = { 0 };printf("%zd\n", sizeof(u)); 联合体的特点123456union Un u = { 0 };printf("%zd\n", sizeof(u));printf("%p\n", &u.a);printf("%p\n", &u.x);printf("%p\n", &u); 发现输出的地址都是一样的 再调试查看一次 1234union Un u = { 0 };printf("x = %d\n", u.x);u.a = 1;printf(&...
结构体
结构体结构体是一些值的合集,这些值称为成员变量 成员变量可以是标量、数组、指针甚至是其他结构体 结构体的声明 1234 struct tag{ member-list;};variable - list; 假如要描述一个学生 1234567struct Stu { char name[20]; // 姓名 int age; // 年龄 char sex[5];// 性别 char id[20]; // 学号}; 结构体变量的初始化12345678910111213141516171819202122232425262728// 变量的定义struct Stu { char name[20]; // 姓名 int age; // 年龄 char sex[5];// 性别 char id[20]; // 学号};struct Stu stu1 = { "张三",18,"male","23001" }; // 一般初始化struct Stu s...
数据在内存中的存储
一、整数在内存中的存储整数二进制的表示方法有三种:原码、反码、补码三种表示方法均由符号位和数 值位组成符号位用 0 表示正数,用 1 表示负数最高位当作符号位,其余均为数值位 正整数的原码、反码、补码都相同 负整数的原码就是二进制表示形式,最高位是 1 负整数的反码是符号位不变,数值位全部取反(0变1,1变0) 负整数的补码是反码 + 1 对于整形来说:数据存在内存中存放的是补码 计算机硬件只有加法器,没有专门的减法器,补码可以把减法完全转换成加法运 算;同时补码解决了「数字 0 有两种编码」的歧义、最大化利用二进制编码空 间、让符号位直接参与运算,是兼顾硬件简单、运算高效、编码规范的最优方 案。 二、大小端字节序和字节序判断大端字节序:数据的低位字节内容放在高地址处,高位字节内容保存在内存的低地址处 小端字节序:数据的低位字节内容放在低地址处,高位字节内容保存在内存的高地址处 在 visual studio 2026 中采用的是小端字节序存放数据。 2.1 设计程序判断当前环境的大小端字节序对 1 取出来一个字节的地址,解应用是 1 就是小端字节序,是 0 就是大端字节序 ...
C语言字符函数和字符串函数
字符分类函数C语言中有一系列的函数是做字符分类的,包含在头文件 ctype.h中 字符转换函数C语言提功了2个字符转换函数 12int tolower(int c) // 将参数传进去的大写字母转小写int toupper(int c) // 将参数传进去的小写字母转大写 12345678910111213141516int i = 0;char str[] = "HelLO woRLd!\n";for (int i = 0;i < sizeof(str) / sizeof(str[0]);i++){ if (islower(str[i])) { // 小写转大写 str[i] = toupper(str[i]); } else if (isupper(str[i])) { //大写转小写 str[i] = tolower(str[i]); }}printf("%s", str); strlen用于求一个字符串的长度,包含在头文件<string.h>...





