VS2005里面 _countof 的实现

先看一下VS2005里面_countof的定义(在stdlib.h里面):

/* _countof helper */

#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

 

————————————————————华丽分割线————————————————————————

 

我们一步步的来对其进行解剖……

 

我们只看C++定义:

extern "C++"

{

template <typename _CountofType, size_t _SizeOfArray>

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

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

}

 

 ||

 ||

 //

 

看得有点费力,简化一下定义如下:

template <typename T, size_t size>

char (*__countof_helper(T (&_Array)[size]))[size];

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

 

 ||

 ||

 //

 

则对于

int Array[100];

 _countof(Array)

 

这样的代码进行宏展开为:

sizeof(*__countof_helper(Array))

 

__countof_helper不知道是啥,先放这里。

 

回头再看看那个模板,先回顾几个知识点:

知识点一:数组指针

char (* pArrayPtr)[size];

 

那么 pArrayPtr 就是一个指向包含 size 个元素的 char 数组的指针(注意那个小括号的作用,它影响了C++语法解析的优先级,如果没有小括号那么就是定义了一个普通的数组,数组中的每个成员都是一个char*):

 

再看 char (*__countof_helper( T ( &_Array)[size] ) )[size];(为了清楚,使用了颜色进行区分)

 

 ||

 ||

 //

 

看红色和绿色的部分,显然:__countof_helper(T (&_Array)[size]) 是一个函数声明,而其他部分则是该函数的返回类型,实际上就是返回一个指针数组。

而函数 __countof_helpe 参数是 T(&_Array)[size]

这里又有一个知识点,T(&_Array)[size] 是一个数组引用。知识点二:数组引用,这里参数使用数组引用就会保证传入的实际数组大小(size)和参数声明的数组大小是完全一致的。

 

 ||

 ||

 //

 

再看回 sizeof(*__countof_helper(Array))__countof_helper(Array)看似一个函数调用,但是实际上不会调用函数,而是直接进行编译期计算(sizeof是一个关键字,它直接在编译时计算传给它的表达式的类型的大小,没有运行时语义),此处会引发编译器模板推导,会推导出(根据int Array[100])函数原型:__countof_helper(int (&_Array)[100]) 返回值类型为:char (* pArrayPtr)[100],则sizeof(*__countof_helper(Array))里面对char (* pArrayPtr)[100]进行解引用再取sizeof的结果就是100(因为pArrayPtr就是一个指向100个元素的char数组指针,使用*解引用操作符之后就是一个100元素的char类型的数组)!!很犀利。

 

有几个问题:

1、微软为什么改成这样?而不用#define _countof(_Array) (sizeof(_Array) / sizeof(_Array[0]))这种直观的方式?有一点很重要是新方法能够进行参数类型检测了,非数组类型不能再传入_countof了,而之前是无法检查的。后来在网上看了老外的一篇文章,对这种方法的好处进行了描述,见http://blog.csdn.net/magictong/archive/2011/04/17/6329485.aspx

2、这里面涉及到哪些知识点……?数组指针,数组引用,模板?

 

你可能感兴趣的:(c,微软,编译器)