文章目录
- 1. `#`(字符串化操作符)
- 作用:
- 示例:
- 2. `##`(符号连接操作符)
- 作用:
- 示例1:动态生成变量名
- 3. `volatile` 关键字
- 作用:
- 示例:
- 4. `static` 关键字
- 作用:
- 示例:
- 5. `new/delete` 与 `malloc/free` 的区别
- 6. 内存分配方式
- 7. 堆与栈的区别
1. #
(字符串化操作符)
作用:
#
用于将宏定义中的传入参数名转换成用一对双引号括起来的字符串。
示例:
#define example1(instr) #instr
string str = example1(abc);
展开后:
string str = "abc";
2. ##
(符号连接操作符)
作用:
##
是一个特殊的连接操作符,称为“令牌粘贴运算符”(Token Pasting Operator)。它的作用是将两个预处理令牌(token)连接成一个单独的标识符。
示例1:动态生成变量名
#define DECLARE_VAR(type, name) type name##Var
int main() {
DECLARE_VAR(int, My); // 展开为:int MyVar;
MyVar = 10;
printf("%d\n", MyVar); // 输出:10
return 0;
}
宏定义解析:
DECLARE_VAR(type, name)
宏将type
和name##Var
连接起来。name##Var
形成新变量MyVar
。
3. volatile
关键字
volatile
提醒编译器,变量的值可能随时变化,因此每次访问时都必须直接从内存读取,而不能使用缓存寄存器的值。
作用:
- 防止编译器优化,使变量始终从内存读取。
- 适用于多线程、硬件寄存器等需要实时访问的变量。
示例:
volatile int flag = 0;
while (flag == 0) {
// 等待 flag 变为非 0
}
4. static
关键字
static
关键字在 C 语言中有多种用途:
作用:
- 函数内部:
- 变量只会被初始化一次,后续调用时保持其值不变。
- 文件内部:
- 变量仅在当前文件内可见,不可被外部文件访问。
- 函数声明:
- 只允许在本文件内部调用,不能被其他文件调用。
示例:
static int count = 0; // 仅在当前文件可用
static void myFunction() { // 仅在当前文件可用
static int num = 10; // 只初始化一次
num++;
printf("%d\n", num);
}
5. new/delete
与 malloc/free
的区别
区别点 | new/delete | malloc/free |
---|---|---|
类型 | C++ 操作符 | C 标准库函数 |
构造/析构 | new 调用构造函数,delete 调用析构函数 | 仅分配/释放内存,不调用构造/析构函数 |
返回值 | 返回指定类型指针 | 返回 void* 需转换 |
内存大小计算 | 自动计算对象大小 | 需手动指定大小 |
适用范围 | C++ 对象管理 | C 语言动态内存管理 |
6. 内存分配方式
类型 | 分配时间 | 释放时间 | 存储位置 | 生命周期 | 适用场景 |
---|---|---|---|---|---|
静态存储区 | 编译时 | 程序结束 | 静态存储区 | 全局 | 全局变量、静态变量 |
栈上分配 | 函数调用 | 函数返回 | 栈 | 函数执行期间 | 局部变量 |
堆上分配 | 运行时 | 手动释放 | 堆 | 直到手动释放 | 动态数据结构 |
7. 堆与栈的区别
区别点 | 堆(Heap) | 栈(Stack) |
---|---|---|
申请方式 | malloc/free | 由系统自动管理 |
申请大小 | 受虚拟内存限制,较大 | 一般 1-2MB(固定) |
申请效率 | 慢,可能产生碎片 | 快,由系统管理 |
存储位置 | 堆区 | 栈区 |
生命周期 | 需手动管理 | 自动管理 |
适用场景 | 适合存储大对象 | 适合小对象和局部变量 |