C++ 学习 ---cstdbool 和 cstddef 源码学习分析
引言
cstdbool 是 C++对 stdbool.h 头文件的封装,里面定义了与 bool 变量相关的宏;
cstddef 是 C++对 stddef.h 头文件的封装,里面定义一些特殊类型(如 size_t),有用的宏函数(offsetof)。
平时我们都是使用这些宏或者宏函数,对于它们的原理还不是很清楚,是怎么实现这些功能的呢?接下来我们就一一来看一看源码实现。
stdbool.h
cstdbool 实现
代码参考:http://www.aospxref.com/android-13.0.0_r3/xref/external/libcxx/include/cstdbool
在 cstdbool 文件中的逻辑很简单,解除__bool_true_false_are_defined 的定义,然后将其定义为 1,标识 bool,true,false 都已经被 C++定义了。
C 语言的原生实现 stdbool.h
在该文件中,如果当前不是 C++环境,那么我们将 bool/true/false 都进行定义,同时将__bool_true_false_are_defined 定义为 1,以便后续使用。
总结
stdbool.h 实际上是为了解决 C/C++的兼容问题出现的。
stddef.h
常量 NULL 的定义
从这里可以看出,实际上 NULL 有三种实现方式,0L,((void*)0)都是我们在 C 语言中常用的方式,其中的 nullptr 是 C++定义的内部类型,能够做到对很多情况的适配,不是一个单独的基本类型。
类型的定义
其中定义了如下的类型:
ptrdiff_t---保存指针减法的结果
size_t---无符号整数,表示类型占据的 size 大小
max_align_t---最大默认对齐的类型
nullptr_t---C++中的空指针类型参考代码:http://www.aospxref.com/android-13.0.0_r3/xref/prebuilts/build-tools/sysroots/x86_64-linux-musl/include/bits/alltypes.h
x86_64 的相关实现如下:ptrdiff_t 使用 long 定义,指针减法,实际上是 64 位数的减法,long 足够表示;size_t 使用 long 表示;max_align_t 定义为拥有 long long 数据和 long double 数据的结构体;nullptr_t 定义为 nullptr 的类型。
offsetof 宏
offsetof (type,member)接受两个参数,类型和成员名,返回该成员的偏移地址。
听上去这个实现起来很简单,我们来看看这个精巧的宏是如何设计的。
不考虑使用内建函数实现的方式,我们来看看第二种方式,这是一个比较复杂的宏,让我们来一步步拆开它,并体会其中的精妙:
((size_t)( (char *)&(((type *)0)->member) - (char *)0 ))
第一步:返回值类型强转为 size_t,规范为 byte 数,也即是偏移量;
(char *)&(((type *)0)->member) - (char *)0
第二步:char*指针转换然后做减法,得到 byte 数的差值;
第三步:((type )0)->member 这里使用了 0 指针强转为 type 指针,然后指向成员 member,此时这个变量的地址相当于 0+member 偏移,然后取地址,指针转换为 char*后做减法
这个方法的好处在于,只使用了 0 指针,没有通过其它变量的构造,很简单地找到了偏移地址,而且这个过程中做的每一步类型转换都是必要的。具体细节读者可以再品味一下,这也是我们阅读源码的收获。
版权声明: 本文为 InfoQ 作者【桑榆】的原创文章。
原文链接:【http://xie.infoq.cn/article/7bfd92891f16c4004ee11a566】。文章转载请联系作者。
评论