ArraySizeHelper解析

  以下代码用于获取一个数组的元素个数,例如 int table[100],以下宏返回100。

template <typename T, size_t N>
char (&ArraySizeHelper(const T (&array)[N]))[N];
#define arraysize(array) (sizeof(ArraySizeHelper(array)))

要点

 1、数组的引用

  T (&)[N] (注意:有个括号)。比如:
  int a[5] = {0};
  int (&ra)[5] = a; 这里ra就是一个对数组a的引用,其这个数组的大小也是5;

 2、返回值为数组引用的函数

  T (& Fun( param_list ) )[N];
  Fun是一个函数,其返回值类型是 T (&)[N];

 3、sizeof()在编译期完成,与运行时无关

  sizeof是C/C++语言中的keyword,不是函数。对其参数里的表达式是不会在执行期去执行的,而只是在编译期去推算整个表达式的最后的类型信息。
  比如: int a = 1; sizeof(a++); cout << a;   // a还是1. 不会是2;
  因为是在编译期完成,编译器只需要类型信息,不需要函数的实现体。所以就可以不用提供定义体。
  下面这个例子可能更能说明这个问题。
  int Fun(); // only declare it without definition
  sizeof( Fun() );  // 这里Fun()函数不会在运行的时候被执行,仅仅是在编译时,编译器需要知道的是:Fun()函数返回值的类型是什么。

 4、模板自动推导在编译期完成

  模板推导是由编译器在编译期(compile time)完成的,而不是在执行期(run time)完成的。

  这个是理解的关键之一。不涉及内存布局分配的问题。编译期间,编译器只关心声明信息(也就是声明式里面所带的类型信息)。模板推导会自动推导模板参数的各种信息(类型,传递过来的数值等)。以下是一个例子:
  template<int x, int y>
  struct sum_
  {
    enum { value = x + y };
  };
  int sum = sum_<3, 4>::value; // sum的值在编译期间就已经确定下来了,不是在执行期间由CPU运算得到。
  这个例子里的模板,仅仅只有数值的传递,没有包含类型。这个可能大家很少见到的。但是模板是支持的。

  例子二:
  template< typename T, size_t N>
  void Fun( T (&)[N] );

  这个模板里既有类型T,又有数值N;模板推导时,是根据Fun的实参来推导得到的。比如:
  int a[5];
  Fun(a); // 编译器经过推导就知道,T=int,N=5。注意这里的N能得到5,是因为Fun的参数声明决定的。这里Fun的参数是:数组引

   5、sizeof(一个指针)和sizeof(一个数组)有很大区别
  
  int a[5];

  int *p = a;
  int (*pa)[5] = &a;

  // p和pa都是指针,但是指针的类型不同:p的类型是int*;pa的类型是int(*)[5]。

  sizeof(p)       // = 4;
  sizeof(a)       // = 20 = 5*sizeof(int)
  sizeof(*p)     // = sizeof(int) = 4;
  sizeof(pa)    // = 4;
  sizeof(*pa)  // = sizeof(a) = 20;

 6、跨函数类型信息丢失

  C/C++对于数组和指针是明确区分其类型的。数组的信息包括(类型+大小),而指针则没有大小信息。
  在这里附带要说一下,数组经过函数参数传递后,数组的大小信息就丢失了。比如:
  void Fun( int a[5] )
  {   
      int n = sizeof(a);  // n为4,相对于就是sizeof(int*).因为编译器只传递过来了数组的地址,大小信息没有了。
  }

  所以,上面Fun的参数声明里面的数组的具体数字是被忽略掉的。其等价声明式可以是:
  void Fun( int a[10] );
  void Fun( int a[] );
  void Fun( int *a );

  为了需要把大小信息传递到函数里面去,需要额外加一个参数来表示大小信息,这个大小信息需要调用者来提供,并且有调用者来保证大小信息的正确性。
  void Fun( int a[], int size );

 

  

ArraySizeHelper解析的更多相关文章

  1. 【原】Android热更新开源项目Tinker源码解析系列之三:so热更新

    本系列将从以下三个方面对Tinker进行源码解析: Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Android热更新开源项目Tinker源码解析系列之二:资源文件热更新 A ...

  2. .NET Core中的认证管理解析

    .NET Core中的认证管理解析 0x00 问题来源 在新建.NET Core的Web项目时选择“使用个人用户账户”就可以创建一个带有用户和权限管理的项目,已经准备好了用户注册.登录等很多页面,也可 ...

  3. Html Agility Pack 解析Html

    Hello 好久不见 哈哈,今天给大家分享一个解析Html的类库 Html Agility Pack.这个适用于想获取某网页里面的部分内容.今天就拿我的Csdn的博客列表来举例. 打开页面  用Fir ...

  4. 【原】Android热更新开源项目Tinker源码解析系列之一:Dex热更新

    [原]Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Tinker是微信的第一个开源项目,主要用于安卓应用bug的热修复和功能的迭代. Tinker github地址:http ...

  5. 【原】Android热更新开源项目Tinker源码解析系列之二:资源文件热更新

    上一篇文章介绍了Dex文件的热更新流程,本文将会分析Tinker中对资源文件的热更新流程. 同Dex,资源文件的热更新同样包括三个部分:资源补丁生成,资源补丁合成及资源补丁加载. 本系列将从以下三个方 ...

  6. 多线程爬坑之路-Thread和Runable源码解析之基本方法的运用实例

    前面的文章:多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类) 多线程爬坑之路-Thread和Runable源码解析 前面 ...

  7. Asp.Net WebApi核心对象解析(下篇)

    在接着写Asp.Net WebApi核心对象解析(下篇)之前,还是一如既往的扯扯淡,元旦刚过,整个人还是处于晕的状态,一大早就来处理系统BUG,简直是坑爹(好在没让我元旦赶过来该BUG),队友挖的坑, ...

  8. 【知识必备】内存泄漏全解析,从此拒绝ANR,让OOM远离你的身边,跟内存泄漏say byebye

    一.写在前面 对于C++来说,内存泄漏就是new出来的对象没有delete,俗称野指针:而对于java来说,就是new出来的Object放在Heap上无法被GC回收:而这里就把我之前的一篇内存泄漏的总 ...

  9. SQL Server 数据加密功能解析

    SQL Server 数据加密功能解析 转载自: 腾云阁 https://www.qcloud.com/community/article/194 数据加密是数据库被破解.物理介质被盗.备份被窃取的最 ...

随机推荐

  1. 08_Java基础语法_第8天(Eclipse)_讲义

    今日内容介绍 1.Eclipse开发工具 2.超市库存管理系统 01Eclipse的下载安装 * A: Eclipse的下载安装  * a: 下载 * http://www.eclipse.org ...

  2. Head First Java & final

  3. Effective Modern C++翻译(6)-条款5:auto比显示的类型声明要更好

        在概念上说,auto关键字和它看起来一样简单,但是事实上,它要更微妙一些的.使用auto会让你在声明变量时省略掉类型,同时也会防止了手动类型声明带来的正确性和性能上的困扰:虽然按照语言预先定义 ...

  4. js 代码几种方式

    var nameSpace={ //public } (function(){ //private })(); var module=(function(){ //private return { / ...

  5. 关于SVM数学细节逻辑的个人理解(二):从基本形式转化为对偶问题

    第二部分:转化为对偶问题进一步简化 这一部分涉及的数学原理特别多.如果有逻辑错误希望可以指出来. 上一部分得到了最大间隔分类器的基本形式:   其中i=1,2,3...m 直接求的话一看就很复杂,我们 ...

  6. RF相关知识

    前言:下文中的总结都是来自于网络,有的来自与博客,有的来自于维基百科/百度百科,仅仅是为了方便查看.   ASK: ASK:幅移键控调制的简写,例如二进制的,把二进制符号0和1分别用不同的幅度来表示, ...

  7. 【刷题】BZOJ 5418 [Noi2018]屠龙勇士

    www.lydsy.com/JudgeOnline/upload/noi2018day2.pdf Solution 将攻击的式子列出来,\(atk \times x-p \times y=a_i\) ...

  8. Udp广播的发送与接收(C#+UdpClient) 上篇

    简介: Udp广播消息用在局域网的消息传递很方便.本文使用UdpClient类在WPF下实现Udp广播收发 发送: void MainWindow_Loaded(object sender, Rout ...

  9. BZOJ 3093: [Fdu校赛2012] A Famous Game

    3093: [Fdu校赛2012] A Famous Game Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 242  Solved: 129[Subm ...

  10. 使用regsrv32.exe绕过应用程序白名单(多种方法)

    0x00 regsvr简介 regsvr32表示Microsoft注册服务.它是Windows的命令行实用工具.虽然regsvr32有时会导致问题出现,但它是Windows系统文件中的一个重要文件.该 ...