读懂_countof,可以懂得什么

时间:2023-03-10 02:58:25
读懂_countof,可以懂得什么

在c++开发中数组是我们经常使用存储结构,而于此同时“数组越界”是每个c++程序员不能不提防陷阱。

还好,我们有预定义宏_countof。

一.在visual c++开发环境下,它的定义如下:

#if !defined(_countof)

#if !defined(__cplusplus)

#define _countof(_Array) (sizeof(_Array) / sizeof(_Array[0]))

#else

extern "C++"

{

template <typename _CountofType, size_t _SizeOfArray>

char (*__countof_helper(UNALIGNED _CountofType (&_Array)[_SizeOfArray]))[_SizeOfArray];

#define _countof(_Array) sizeof(*__countof_helper(_Array))

}

#endif

#endif

能引发兴趣的显然是__countof_helper,我们抽茧剥丝的看一下。

template <typename _CountofType, size_t _SizeOfArray>

char (*__countof_helper(UNALIGNED _CountofType (&_Array)[_SizeOfArray]))[_SizeOfArray];

1. 它是一个函数模板的声明,并没有函数体;

2. 它有一个参数,类型为_CountofType(&)[_SizeOfArray]的数组引用;

3. 它的返回值是一个指向数组的指针,类型为 char (*)[_SizeOfArray];

这里有几个知识点需要注意一下。

1. 数组引用

2. 数组指针

3. 模板函数

4. 数组指针的解引用

理解了函数模板__countof_helper,我们再来看看宏_countof.

#define _countof(_Array) sizeof(*__countof_helper(_Array))

可以看到,它本质是对函数__countof_helper的返回值进行了解引用之后的sizeof

而返回值是指向数组的指针,解引用之后自然就是数组本身了。

对一个char类型的数组求大小,也就是数组的大小(元素个数)了。

二.在Linux 内核中,有一个类似的求数组大小的宏ARRAY_SIZE

它的定义为:

#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))

其中__must_be_array被定义为

/* &a[0] degrades to a pointer: a different type from an array */

#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))

__same_type()又被定义为

#define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))

BUILD_BUG_ON_ZERO是编译时期的断言宏,检查表达式e是否为0,为0编译通过且返回0;如果不为0,则编译不通过。

__builtin_types_compatible_p用来判断type1和type2是否是相同的数据类型,相同返回1,否则返回0。

一个小小的宏,有这么多东西,是不是感觉赚到了 :)

Ref:

http://www.cnblogs.com/liuzhanshan/p/6861596.html

http://www.cnblogs.com/hazir/p/static_assert_macro.html

https://msdn.microsoft.com/en-us/library/b0084kay(v=vs.100).aspx

https://*.com/questions/8018843/macro-definition-array-size/8021113#8021113