一、存储类别关键字

1. auto(自动存储)

  • 数据存储在
  • 自动申请、自动释放

2. static(静态存储)

  • 数据存储在静态区(全局区)
  • 生命周期为整个程序运行期间

静态区变量初始化规则:

  • 只能用常量初始化,不能用变量初始化
  • 只需要初始化一次

static修饰局部变量:

  • 值具有继承性(保持上次的值)
  • 延长了局部变量的生命周期

static修饰全局变量/函数:

  • 限定作用域为本文件
  • 其他文件通过extern也无法引用
  • 作用:保护数据,防止命名冲突

3. extern(外部声明)

  • 声明所用的变量或函数是在外部定义的
  • 作用:扩展标识符的作用域
  • 可以让全局变量在整个工程中使用

4. register(寄存器)

  • 建议编译器将变量存储在寄存器中(仅建议)
  • 不能对register变量取地址(&运算)
  • 用于频繁访问的变量,提高效率

计算机存储体系(按速度排序):

CPU → 寄存器 → Cache(高速缓存)→ 内存 → 硬盘

容量:小 ←→ 大
速度:快 ←→ 慢
价格:贵 ←→ 便宜

二、编译过程

GCC编译的4个阶段

hello.c → [预处理] → [编译] → [汇编] → [链接] → a.out
  1. 预处理:处理预处理命令,生成纯C语言文件
  2. 编译:将C代码编译为汇编代码
  3. 汇编:将汇编代码翻译为机器指令
  4. 链接:将相关代码链接成最终可执行文件

三、预处理命令

所有预处理命令都以 # 开头

1. 宏定义

(1)普通宏(符号常量)
#define PI 3.14
#define 宏名 宏值

作用:

  • 用宏名代替宏值(文本原样替换)

好处:

  • 方便修改,一改全改
  • 提高代码可读性
(2)带参宏
#define S(r) (PI*(r)*(r))
#define 宏名(参数表) 宏值

使用示例:

printf("S = %f\n", S(2));  // 展开为:PI*2*2

注意事项:

  • 带参宏形式像函数,但不是函数
  • 避免副作用:能加括号的地方都加上
  • 宏名约定用大写(与变量、函数区分)
  • 宏定义这一行不要写分号
  • 宏的作用域:从定义处到文件末尾(或#undef处)
  • 使用 #undef 宏名 可终止宏的作用

带参宏 vs 函数:

对比项 带参宏 函数
处理阶段 预处理阶段 编译阶段
参数类型 无类型 有类型检查
代码体积 可能变大(每次展开) 只有一份代码
适用场景 简短代码(≤5行) 复杂逻辑

续行符:

  • 宏定义结束标志是换行符
  • 使用 \ 可以续行

2. 文件包含

#include <stdio.h>  // 系统头文件,在系统路径查找
#include "myhead.h" // 自定义头文件,先在当前目录查找

区别:

  • #include <>:直接到系统路径查找
  • #include "":先查找当前目录,找不到再查系统路径

作用:

  • 将指定文件的内容替换到当前位置

3. 条件编译

选择性地编译某些代码

形式1:#ifdef
#ifdef 标识符
    程序段1
#else
    程序段2
#endif

含义:如果定义了标识符,编译程序段1,否则编译程序段2

形式2:#ifndef
#ifndef 标识符
    程序段1
#else
    程序段2
#endif

含义:如果没有定义标识符,编译程序段1,否则编译程序段2

形式3:#if
#if 表达式
    程序段1
#else
    程序段2
#endif

含义:如果表达式为真,编译程序段1,否则编译程序段2

实用技巧:

#if 0
    // 这段代码不会被编译(相当于注释掉大段代码)
#endif

四、知识点小结

重要概念

  1. 标识符作用域和可见性
  2. 局部变量 vs 全局变量
  3. 变量的生命周期

存储类别关键字总结

  • auto:栈上自动存储(默认)
  • static:静态区存储,延长生命周期或限定作用域
  • register:建议存储在寄存器
  • extern:声明外部变量/函数

预处理核心

  • 文本原样替换
  • 提高编译效率和代码可维护性

    作业

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐