当前位置: 首页 > news >正文

面试八股:C语言的预处理和类型定义

目录

一,define 和 typedef 的区别

1.1 概念

1.2 用法和区别

1.3 优缺点

二,常见宏的使用

2.1 宏的定义和使用

2.3 注意事项

三,# 和 ## 区别

3.1 # 操作符:字符串化

3.2 ## 操作符:连接符

3.3 区别

四,offsetof 的作用与实现

4.1 定义

4.2 实现原理

五,container_of 的实现

5.1 定义

5.2 原理

六,typeof

七,C/C++ 最佳实践


C 语言作为一门经典的系统编程语言,它的预处理器指令和类型定义

为开发者提供了强大的灵活性

本文档主要探讨:

  1. C 语言中 define 和 typedef 的区别
  2. 常见宏的使用
  3. 预处理器操作符 # 和 ##
  4. offsetof,container_of 和 typeof 的实现

一,define 和 typedef 的区别

1.1 概念

  • define:
    • C 预处理指令,用于定义宏
    • 编译前的预处理阶段将宏名替换为对应的内容,是一种文本替换机制
    • 可以定义常量,函数宏
#define PI 3..14159 // 常量宏
#define MAX(a, b) ((a) > (b) ? (a) : (b)) // 函数宏
  • typedef:
    • C 语言关键字,为现有类型定义别名
    • 编译阶段起作用,是一种类型定义机制,用于简化复杂声明

ulong 是 unsigned long 的别名,Point 是结构体的别名

typedef unsigned long ulong;
typedef struct {int x;int y;
} Point;

1.2 用法和区别

  • 作用阶段:
    • define 在预处理阶段文本替换
    • typedef 在编译阶段类型解析
  • 功能差异:
    • define 只是简单的文本替换,不涉及类型检查,可能导致错误
    • typedef 定义的是类型别名,编译器会进行类型检查
  • 适用场景:
    • define 定义常量或简单的宏
    • typedef 可以为复杂类型定义别名(如结构体,指针)
#define INT_PTR int* // 文本替换
typedef int* IntPtr; // 类型别名INT_PTR a, b; // 展开后为 int* a, b;  只有 a 是指针,b 是 int
IntPtr c, d; // c 和 d 都是 int* 类型

1.3 优缺点

  • define:灵活,可定义常量和宏,但缺乏类型检查,易出错
  • typedef:类型安全,提高可读性,仅限于类型别名

二,常见宏的使用

2.1 宏的定义和使用

宏通过 define 定义,用于在编译前,进行文本替换

  • 常量宏
#define BUFFER_SIZE 1024
char buffer[BUFFER_SIZE];
  • 调试宏
#ifdef DEBUG // 如果已定义 DEBUG 宏
#define LOG(msg) printf("Debug: %s\n", msg) // 执行这行
#else // 如果未定义
#define LOG(msg) // 为空
#endif // 结束条件编译
LOG("Function started");
  • 函数宏
#define MIN(a, b) ((a) < (b) ? (a) : (b))
int smaller = MIN(5, 10);

2.3 注意事项

  • 避免副作用:函数宏参数可能多次求职,需要加括号保护
  • 代码膨胀:复杂的宏,会导致编译后代码体积增大

三,# 和 ## 区别

3.1 # 操作符:字符串化

  • 作用:将宏参数转化为字符串字面量,用于调试
#define PRINT_VAR(var) printf(#var " = %d\n", var)
int x = 42;
PRINT_VAR(x); // 输出 x = 42

3.2 ## 操作符:连接符

  • 作用:两个标识符被连接,成为新的标识符,用于代码生成
#define CONCAT(prefix, suffix) prefix ## suffix
int CONCAT(var_, 1) = 100; // 展开为 int var_1 = 100;

3.3 区别

  • 区别:# 转为字符串,## 连接标识符
  • 应用:# 用于日志,## 生成变量名

四,offsetof 的作用与实现

4.1 定义

offsetof 是 C 标准宏,定义在 <stddef.h> 中,用于计算按结构体成员的偏移量

#include <stddef.h>
#include <stdio.h>
struct Example { char a; int b; double c; };
int main() {printf("Offset of a: %zu\n", offsetof(struct Example, a)); // Offset of a: 0printf("Offset of b: %zu\n", offsetof(struct Example, b)); // Offset of b: 4return 0;
}

4.2 实现原理

type 是结构体,member 是 type 的一个成员

#define offsetof(type, member) ((size_t)&(((type *)0)->member))
  • 解释:
    • 将 0 转化成结构体指针
    • 假设结构体在地址 0,然后访问成员 member 的地址
    • 由于结构体起点是 0,成员的地址就是偏移量
    • 最后转为 size_t 类型返回
    • 这个过程在编译时完成,不真正访问内存,只是利用编译器计算偏移
  • 使用场景:
    • 内存布局:调试 OR 优化内存对齐
    • 指针操作:结合指针访问成员

五,container_of 的实现

5.1 定义

container_of 用于 Linux 内核,通过成员指针反向获取结构体指针

#define container_of(ptr, type, member) ((type *)((char *)(ptr) - offsetof(type, member)))
  struct Person { int id; char name[20]; };int main() {struct Person p = {1, "Alice"};char *name_ptr = p.name;struct Person *person_ptr = container_of(name_ptr, struct Person, name);printf("ID: %d\n", person_ptr->id);return 0;}

5.2 原理

  • 原理:offsetof 获取偏移量,成员指针 - 偏移量得到结构体地址
  • 使用场景:
    • 嵌入式:通过成员访问结构体
    • 数据结构:链表中反向获取节点

六,typeof

定义

  • typeof 是 GCC 扩展关键字,用于获取表达式类型,C++ 用 decltype
  int x = 10;typeof(x) y = 20; // 等价于 int y = 20;

应用:用于宏,确保类型一致性

  #define SWAP(a, b) do { typeof(a) temp = a; a = b; b = temp; } while(0)int x = 1, y = 2;SWAP(x, y);

七,C/C++ 最佳实践

    • 最小化使用:优先 const 代替宏
    • 括号保护
  • 类型定义
    • 优先 typedef,确保类型安全
    • 命名规范:类型别名后缀加 _t
  • 内存操作
    • 谨慎使用 offsetof 和 container_of:要确保指针有效
    • 内存对齐:优化结构体成员顺序
  • 跨平台
    • 条件编译:使用宏确保跨平台兼容
http://www.dtcms.com/a/395847.html

相关文章:

  • 强化学习1.3 深度学习交叉熵方法
  • 用PowerBI的思想解决QuickBI文本无法动态配色问题
  • 逆向解析 1688 商品详情接口:自主构建 Sign 签名算法实战
  • SpringCloud项目阶段六:feign服务降级处理以及基于DFA算法的自管理敏感词审核和tess4j图片文字识别集成
  • 跨行业安全合规文档协同平台:重塑制造企业的质量管理与合规运营新范式
  • 线性代数 · SVD | 奇异值分解命名来历与直观理解
  • Qt 控件与布局
  • TDengine 聚合函数 SPREAD 用户手册
  • 4090 云服务器租赁:高性能与灵活性的算力融合方案​
  • 阿里云服务器ECS上安装anaconda(jupyter)和OpenCV教程
  • CVE-2025–3246 本地提权
  • Chat API和Chat SDK
  • 爱奇艺技术实践:基于 StarRocks 释放天玑买量数据价值
  • 突破传统文本切分桎梏!基于语义理解的智能文档处理革命——AntSK-FileChunk深度技术解析
  • Git常用的使用方法
  • IDEA集成Claude Code (win系统)
  • MySQL执行计划:索引为何失效?如何避免?
  • 【附源码】基于SpringBoot的校园防汛物资管理平台的设计与实现
  • PyTorch 核心工具与模型搭建
  • ARM--时钟管理单元与定时器
  • Unity-动画基础
  • 逻辑回归中的决策边界解析与应用实例
  • 设计模式——结构型模式(下)
  • CANoe中封装SeedKey安全解锁函数的完整指南
  • Vue树选择
  • opencv人脸识别
  • 怿星科技桂林子公司乔迁新址,于山水画中开启研发新篇章
  • 创建者模式:工厂方法模式
  • 【 C/C++ 算法】入门动态规划-----路径问题(以练代学式)
  • 三.上网行为安全