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

内部标识符

内部标识符

这是 C 语言标准的一种约定(如 C 标准库中的很多内部结构会采用类似命名)。这样可以降低用户自定义标识符与系统库、编译器内部符号或其他模块的命名冲突风险。

例子1:标准库中的内部实现与外部接口分离

C语言标准库中很多类型就是这样设计的,比如 FILE 结构体(用于文件操作):

// 标准库内部定义(我们看不到的实现)
typedef struct _IO_FILE_ {// 复杂的内部成员(文件描述符、缓冲区等)int fd;char* buffer;// ... 其他内部细节
} _IO_FILE;// 对外暴露的接口(我们实际使用的类型)
typedef _IO_FILE FILE;

为什么这样做?

  • 外部代码只需要用 FILE* 操作文件(如 fopen 返回 FILE*),无需知道内部的 _IO_FILE_ 结构细节。
  • 如果未来库开发者想修改 _IO_FILE_ 的内部成员,只要保证 FILE 这个对外类型兼容,用户代码就不需要改动。
  • 下划线避免用户不小心定义一个 IO_FILE 结构体,与标准库冲突。

例子2:项目中模块间的隔离

假设一个大型项目有两个模块:UI模块图形渲染模块,都需要用到“矩形”概念:

// UI模块内部定义
typedef struct _UI_Rect_ {sint32 x;   // 屏幕坐标sint32 y;sint32 w;sint32 h;
} _UI_Rect;
// 对外提供的类型
typedef _UI_Rect UIRect;// 图形渲染模块内部定义
typedef struct _Render_Rect_ {float x;    // 浮点精度坐标(适合渲染)float y;float w;float h;
} _Render_Rect;
// 对外提供的类型
typedef _Render_Rect RenderRect;

为什么这样做?

  • 两个模块内部都用 _XXX_Rect_ 作为实际结构名,即使都包含“Rect”,也不会冲突(因为有模块前缀和下划线)。
  • 对外暴露 UIRectRenderRect,清晰区分用途,用户不会混淆。
  • 如果某天UI模块想改 _UI_Rect_ 的成员(比如加一个 z 轴坐标),只要 UIRect 这个类型名不变,使用UI模块的代码就不用改。

例子3:防止与用户代码重名

假设你开发了一个库,提供一个 Point 结构体:

// 你的库内部
typedef struct _Point_ {int x;int y;
} _Point;
// 对外暴露
typedef _Point Point;

如果用户自己的代码里也定义了一个 Point

// 用户代码
struct Point {float x;float y;
};

为什么安全?

  • 因为库的实际结构是 _Point_,和用户的 Point 完全是两个标识符,不会冲突。
  • 用户用库时,通过 typedef 得到的 Point 是库提供的类型,而用户自己的 struct Point 是另一个类型,编译器能区分。

核心目的总结

下划线包裹的命名本质是一种“内部标识隔离”:

  1. 把“实现细节”(_XXX_)和“对外接口”(XXX)分开,方便维护和升级。
  2. 避免不同模块、不同开发者之间的命名冲突(尤其在没有命名空间的C语言中)。
  3. 明确告诉其他开发者:_XXX_ 是内部的,不要直接修改或依赖它,应该用外层的 XXX

就像现实中,公司内部文件会标“内部机密”,对外则用公开名称,既保护内部细节,又方便外部使用。

http://www.dtcms.com/a/394927.html

相关文章:

  • 计算机网络2
  • 计算机视觉(opencv)实战三十二——CascadeClassifier 人脸微笑检测(摄像头)
  • MyBatis-Plus 全方位深度指南:从入门到精通
  • PyTorch 神经网络工具箱:从组件到基础工具,搭建网络的入门钥匙
  • 分布式专题——18 Zookeeper选举Leader源码剖析
  • JVM 调优在分布式场景下的特殊策略:从集群 GC 分析到 OOM 排查实战(二)
  • 基于OpenEuler部署kafka消息队列
  • Flink TCP Channel复用:NettyServer、NettyProtocol详解
  • Sass和Less的区别【前端】
  • Kotlin互斥锁Mutex协程withLock实现同步
  • Seedream 4.0 测评|AI 人生重开:从极速创作到叙事实践
  • vscode clangd 保姆教程
  • MySQL时间戳转换
  • 【Spark+Hive+hadoop】基于spark+hadoop基于大数据的人口普查收入数据分析与可视化系统
  • 分布式专题——17 ZooKeeper经典应用场景实战(下)
  • TDengine 2.6 taosdump数据导出备份 导入恢复
  • 探索 Yjs 协同应用场景 - 分布式撤销管理
  • 【软考中级 - 软件设计师 - 基础知识】数据结构之栈与队列​
  • LeetCode 385 迷你语法分析器 Swift 题解:从字符串到嵌套数据结构的解析过程
  • windows系统使用sdkman管理java的jdk版本,WSL和Git Bash哪个更能方便管理jdk版本
  • 生产环境K8S的etcd备份脚本
  • Mac电脑多平台Git账号配置
  • Etcd详解:Kubernetes的大脑与记忆库
  • 深刻理解PyTorch中RNN(循环神经网络)的output和hn
  • 大模型如何赋能写作:从创作到 MCP 自动发布的全链路解析
  • C++设计模式之创建型模式:工厂方法模式(Factory Method)
  • 传输层协议——UDP/TCP
  • 三板汇茶咖空间签约“可信资产IPO与数链金融RWA”链改2.0项目联合实验室
  • 【MySQL】MySQL 表文件误删导致启动失败及无法外部连接解决方案
  • LVS简介