在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://stackoverflow.com/questions/8018843/macro-definition-array-size/8021113#8021113

 

版权声明:本文为envoy原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/envoy/p/8352467.html