目录引言stdbool.hcstdbool实现C语言的原生实现stdbool.h小结stddef.h常量NULL的定义类型的定义offsetof宏引言 cstdbool是c++对st
cstdbool是c++对stdbool.h头文件的封装,里面定义了与bool变量相关的宏;
cstddef是C++对stddef.h头文件的封装,里面定义一些特殊类型(如size_t),有用的宏函数(offsetof)。
平时我们都是使用这些宏或者宏函数,对于它们的原理还不是很清楚,是怎么实现这些功能的呢?接下来我们就一一来看一看源码实现。
代码参考:www.aospxref.com/Android-13.…
在cstdbool文件中的逻辑很简单,解除__bool_true_false_are_defined的定义,然后将其定义为1,标识bool,true,false都已经被C++定义了。
#include <__config>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
#pragma GCC system_header
#endif
#undef __bool_true_false_are_defined
#define __bool_true_false_are_defined 1
参考代码:www.aospxref.com/android-13.… 在该文件中,如果当前不是C++环境,那么我们将bool/true/false都进行定义,同时将__bool_true_false_are_defined定义为1,以便后续使用。
#ifndef __cplusplus
#define true 1
#define false 0
#define bool _Bool
#endif
#define __bool_true_false_are_defined 1
stdbool.h实际上是为了解决C/C++的兼容问题出现的。
代码参考:www.aospxref.com/android-13.…
从这里可以看出,实际上NULL有三种实现方式,0L,((void*)0)都是我们在C语言中常用的方式,其中的nullptr是C++定义的内部类型,能够做到对很多情况的适配,不是一个单独的基本类型。
#if __cplusplus >= 201103L
#define NULL nullptr
#elif defined(__cplusplus)
#define NULL 0L
#else
#define NULL ((void*)0)
#endif
其中定义了如下的类型:
x86_64的相关实现如下: ptrdiff_t使用long定义,指针减法,实际上是64位数的减法,long足够表示; size_t使用long表示; max_align_t定义为拥有long long数据和long double数据的结构体; nullptr_t定义为nullptr的类型。
#define _Addr long
#if defined(__NEED_ptrdiff_t) && !defined(__DEFINED_ptrdiff_t)
typedef _Addr ptrdiff_t;
#define __DEFINED_ptrdiff_t
#endif
#if defined(__NEED_size_t) && !defined(__DEFINED_size_t)
typedef unsigned _Addr size_t;
#define __DEFINED_size_t
#endif
#if defined(__NEED_max_align_t) && !defined(__DEFINED_max_align_t)
typedef struct { long long __ll; long double __ld; } max_align_t;
#define __DEFINED_max_align_t
#endif
typedef decltype(nullptr) nullptr_t;
offsetof (type,member)接受两个参数,类型和成员名,返回该成员的偏移地址。
听上去这个实现起来很简单,我们来看看这个精巧的宏是如何设计的。
#if __GNUC__ > 3
#define offsetof(type, member) __builtin_offsetof(type, member)
#else
#define offsetof(type, member) ((size_t)( (char *)&(((type *)0)->member) - (char *)0 ))
#endif
不考虑使用内建函数实现的方式,我们来看看第二种方式,这是一个比较复杂的宏,让我们来一步步拆开它,并体会其中的精妙:
((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指针,没有通过其它变量的构造,很简单地找到了偏移地址,而且这个过程中做的每一步类型转换都是必要的。具体细节读者可以再品味一下,这也是我们阅读源码的收获。
以上就是C++学习之cstdbool和cstddef头文件封装源码分析的详细内容,更多关于C++头文件封装cstdbool cstddef的资料请关注编程网其它相关文章!
--结束END--
本文标题: C++学习之cstdbool和cstddef头文件封装源码分析
本文链接: https://lsjlt.com/news/166843.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2024-03-01
2024-03-01
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0