由chrome源码中的arraysize想到的

在网上看到一段出自chrome的求数组长度的源代码:
  1. template<typename T, size_t N>
  2. char (&ArraySizeHelper((&array)[N]))[N];
  3. #define arraysize(array) (sizeof(ArraySizeHelper(array)))
google为什么不使用我们一般求 数组长度的方法:
  1. #define array_size(array) (sizeof(array) / sizeof(array[0]))
这是因为后者存在瑕疵:当我们传给array_size宏的不是数组名,而是指针的时候,宏array_size不会在编译的时候报错!它会得出错误的结果并且继续运行!而前者改进了后者存在的瑕疵,当我们将一个指针传给arraysize的时候,它会在编译期报错:
  1. #include <iostream>
  2. using namespace std;

  3. template<typename T, size_t N>
  4. char (&ArraySizeHelper((&array)[N]))[N];
  5. #define arraysize(array) (sizeof(ArraySizeHelper(array)))
  6. #define array_size(array) (sizeof(array) / sizeof(array[0]))

  7. int main()
  8. {
  9.     double a[200];
  10.     double *= new double[10];

  11.     std::cout << array_size(a) << std::endl;
  12.     std::cout << array_size(d) << std::endl;   // 这里输出0,因为:(4 / 8) == 0

  13.     std::cout << arraysize(d) << std::endl;    // 这里报错
  14.     std::cout << arraysize(a) << std::endl;

  15.     return 0;
  16. }
上面的代码中:array_size(d)没有报错,他会输出错误的结果:0 !!!
而代码arraysize(d)会报错: error: no matching function for call to 'ArraySizeHelper(double*&)'
这就是两者的区别所在,也是前者的高明所在!!!
 
下面我们来研究一下chrome中的代码:
  1. template<typename T, size_t N>
  2. char (&ArraySizeHelper((&array)[N]))[N];
  3. #define arraysize(array) (sizeof(ArraySizeHelper(array)))
看到代码,进过仔细的思考,会有所理解,也会有一些疑问:
它主要的思想是将数组 T array[N]转化成数组 char ArraySizeHelper[M]. 在转化前后,数组所占的内存大小没有变,所以原数组的大小等于:sizeof(ArraySizeHelper).
这里的疑问是:
array本来就是数组名,也就是数组的首地址,为什么还要在他的前面再加上取地址符&呢?这里我们先看一小段代码:
  1. int main()
  2. {
  3.     double a[200];
  4.   
  5.     printf("a:%p\n&a:%p\n", a, &a);
  6.     return 0;
  7. }
运行这段代码,我们会发现:a和&a的地址是一样的,是相等的!!!
然后,我们将上面的代码改一下:
  1. int main()
  2. {
  3.     double a[200];
  4.     printf("a:%p\n&a:%p\n", a, &a);
  5.     printf("%d\n", (== &a) );
  6.     return 0;
  7. }
编译,它报错:
error: comparison between distinct pointer types 'double*' and 'double (*)[200]' lacks a cast
从这段报错信息,我们可以得出结论:
虽然a和&a的地址值是一样的,是相等的,但是a和&a的类型却是不相同的a的类型是double *,而&a的类型是double (*)[200],a只是一个指针,而&a是一个指向数组的指针(如果可以区分开“指针数组”和“数组的指针”,那么就容易理解了。)这也就解释了:
  1. template<typename T, size_t N>
  2. char (&ArraySizeHelper((&array)[N]))[N];
这里array的前面为什么使用取地址符& ,因为这里需要的是double (*)[200],而不是double * .只有当我们传进去的是double (*)[200],模板的定义才是正确的。
所以当我们将 double *= new double[10];  传给 arraysize(d时,才会在编译的时候报错!!!
另外:代码char (&ArraySizeHelper((&array)[N]))[N];中的两个N他们的值是不一样的:第一个N是double (*)[200]中的200 , 是传进去的值, 而第二个N却是在将array传给char数组的构造函数:
 char (void *)[N]时计算出来的。
 
总结:
chrome中的ArraySizeHelper的定义利用了两点:
《1》利用了指针和数组的区别
《2》利用了char型数组的构造函数:char (void *)[N]来构造出一个新的数组ArraySizeHelper
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
CSDN IT狂飙上的代码均可运行,功能ok的情况下才上的,直接替换数据即可使用,小白也能轻松上手 【资源说明】 基于MATLAB实现的有限差分法实验报告用MATLAB的有限差分法计算槽内电位;对比解析法和数值法的异同点;选取一点,绘制收敛曲线;总的三维电位图+使用说明文档 1、代码压缩包内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2020b;若运行有误,根据提示GPT修改;若不会,私信博主(问题描述要详细); 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可后台私信博主; 4.1 期刊或参考文献复现 4.2 Matlab程序定制 4.3 科研合作 功率谱估计: 故障诊断分析: 雷达通信:雷达LFM、MIMO、成像、定位、干扰、检测、信号分析、脉冲压缩 滤波估计:SOC估计 目标定位:WSN定位、滤波跟踪、目标定位 生物电信号:肌电信号EMG、脑电信号EEG、心电信号ECG 通信系统:DOA估计、编码译码、变分模态分解、管道泄漏、滤波器、数字信号处理+输+分析+去噪、数字信号调制、误码率、信号估计、DTMF、信号检测识别融合、LEACH协议、信号检测、水声通信 5、欢迎下载,沟通交流,互相学习,共同进步!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值