///http://blog.chinaunix.net/space.php?uid=25909722&do=blog&id=2901495
#include <iostream>
using namespace std;
template <typename T,size_t N>
char (&ArraySizeHelper(T (&array)[N]))[N];
#define arraysize(array) (sizeof(ArraySizeHelper(array)))
#define array_size(array) (sizeof(array)/sizeof(array[0]))
int main()
{
double a[200];
double *d=new double[10];
std::cout<< array_size(a)<< std::endl;
std::cout<< array_size(d)<< std::endl;
std::cout<< arraysize(a) << std::endl;
// std::cout<< arraysize(d) << std::endl;
return 0;
}
它主要的思想是将数组 T array[N]转化成数组 char ArraySizeHelper[M]. 在转化前后,数组所占的内存大小没有变,所以原数组的大小等于:sizeof(ArraySizeHelper).
这里的疑问是:
array本来就是数组名,也就是数组的首地址,为什么还要在他的前面再加上取地址符&呢?这里我们先看一小段代码:
- int main()
- {
- double a[200];
-
- printf("a:%p\n&a:%p\n", a, &a);
- return 0;
- }
运行这段代码,我们会发现:a和&a的地址是一样的,是相等的!!!
然后,我们将上面的代码改一下:
- int main()
- {
- double a[200];
-
- printf("a:%p\n&a:%p\n", a, &a);
- printf("%d\n", (a == &a) );
- return 0;
- }
编译,它报错:
error: comparison between distinct pointer types 'double*' and 'double (*)[200]' lacks a cast
从这段报错信息,我们可以得出结论:
虽然a和&a的地址值是一样的,是相等的,但是a和&a的类型却是不相同的。a的类型是double *,而&a的类型是double (*)[200],这也就解释了:
- template<typename T, size_t N>
- char (&ArraySizeHelper(T (&array)[N]))[N];
这里array的前面为什么使用取地址符& ,因为这里需要的是double (*)[200],而不是double * .只有当我们传进去的是double (*)[200],模板的定义才是正确的。
所以当我们将 double *d = new double[10]; 传给 arraysize(d) 时,才会在编译的时候报错!!!
另外:代码char (&ArraySizeHelper(T (&array)[N]))[N];中的两个N他们的值是不一样的:第一个N是double (*)[200]中的200 , 是传进去的值,
而第二个N却是在将array传给char数组的构造函数:
char (void *)[N]时计算出来的。
总结:
chrome中的ArraySizeHelper的定义利用了两点:
《1》利用了指针和数组的区别
《2》利用了char型数组的构造函数:char (void *)[N]来构造出一个新的数组ArraySizeHelper。