在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

读懂_countof,可以懂得什么的更多相关文章

  1. 如何快速读懂大型C++程序代码

    要搞清楚别人的代码,首先,你要了解代码涉及的领域知识,这是最重要的,不懂领域知识,只看代码本身,不可能搞的明白.其次,你得找各种文档:需求文档(要做什么),设计文档(怎么做的),先搞清楚你即将要阅读是 ...

  2. [Interview]读懂面试问题,在面试官面前变被动为主动

    面试是供需双方心理的较量,作为求职者来说,了解对方问题的内涵,做到“明明白白他的心”,就能变被动为主动.因此,读懂面试问题,掌握面试考官的提问的目的,有准备.有针对性地回答,对提高应聘的成功率是有很大 ...

  3. 读懂UI设计的心理学

    好文转载,版权归原作者 作为UI设计师,对待用户就像对待婴儿,知道如何通过界面设计诱导用户非常重要,这就需要了解心理学方面的知识了.今天分享一篇日本设计师的好文,结合心理学与设计,教你读懂心理学,提高 ...

  4. 一文读懂UGC:互联网上的生态秘密

    转载自近乎: UGC(User- Generated Content)用户原创生产内容,它是相对于PGC(Professionally-produced Content)专业生产内容的一种内容来源,简 ...

  5. 读懂IL代码就这么简单(三)完结篇

    一 前言 写了两篇关于IL指令相关的文章,分别把值类型与引用类型在 堆与栈上的操作区别详细的写了一遍 这第三篇也是最后一篇,之所以到第三篇就结束了,是因为以我现在的层次,能理解到的都写完了,而且个人认 ...

  6. 读懂IL代码就这么简单(二)

    一 前言 IL系列 第一篇写完后 得到高人指点,及时更正了文章中的错误,也使得我写这篇文章时更加谨慎,自己在了解相关知识点时,也更为细致.个人觉得既然做为文章写出来,就一定要保证比较高的质量,和正确率 ...

  7. 读懂IL代码就这么简单 (一)

    一前言 感谢 @冰麟轻武 指出文章的错误之处,现已更正 对于IL代码没了解之前总感觉很神奇,初一看完全不知所云,只听高手们说,了解IL代码你能更加清楚的知道你的代码是如何运行相互调用的,此言一出不明觉 ...

  8. 一张图读懂https加密协议

    搭建CA服务器和iis启用https:http://blog.csdn.net/dier4836/article/details/7719532 一张图读懂https加密协议 https是一种加密传输 ...

  9. Gradle学习系列之三——读懂Gradle语法

    在本系列的上篇文章中,我们讲到了创建Task的多种方法,在本篇文章中,我们将学习如何读懂Gradle. 请通过以下方式下载本系列文章的Github示例代码: git clone https://git ...

随机推荐

  1. 实体框架(Entity Frmaework)简介

    l简称EF  NH l与Asp.Net MVC关系与ADO.NET关系 lADO.NET Entity Framework 是微软以 ADO.NET 为基础所发展出来的对象关系对应 (O/R Mapp ...

  2. C# 真正能发邮件的源码

    在网上找了很多例子都试邮件发送都失败,今天无意有试了一下居然行了 public static void ErrorMessageMail(string _subject, string _body)  ...

  3. [APIO2010]特别行动队

    题目描述 你有一支由 n 名预备役士兵组成的部队,士兵从 1 到 n 编号,要将他们拆分 成若干特别行动队调入战场.出于默契的考虑,同一支特别行动队中队员的编号 应该连续,即为形如(i, i + 1, ...

  4. thinkinginjava学习笔记07_多态

    在上一节的学习中,强调继承一般在需要向上转型时才有必要上场,否则都应该谨慎使用: 向上转型和绑定 向上转型是指子类向基类转型,由于子类拥有基类中的所有接口,所以向上转型的过程是安全无损的,所有对基类进 ...

  5. Vuejs实现列表选中效果

    //html <div id="app"> <ul><div>选择你最喜欢的爱好:</div> <li class=" ...

  6. 【Python3之匿名函数及递归】

    一.匿名函数及内置函数补充 1.语法 Python使用lambda关键字创造匿名函数.所谓匿名,意即不再使用def语句这样标准的形式定义一个函数. 语法: lambda [arg1[, arg2, . ...

  7. [Spark内核] 第38课:BlockManager架构原理、运行流程图和源码解密

    本课主题 BlockManager 运行實例 BlockManager 原理流程图 BlockManager 源码解析 引言 BlockManager 是管理整个Spark运行时的数据读写的,当然也包 ...

  8. python学习笔记(四)-数据类型

    0. 在 Python 中的数据类型详解 http://www.cnblogs.com/scios/p/8026576.html 1. 为什么布尔类型(bool)的 True 和 False 分别用 ...

  9. 【转】NO.2、Appium之IOS第一个demo

    接第一篇:Appium之iOS环境搭建 http://blog.csdn.net/clean_water/article/details/52946191 这个实例继承了unittest,重写了它的s ...

  10. 使用MSHTML解析HTML页面

    最近在写一个爬虫项目,本来打算用C/C++来实现,在网上查找有关资料的时候发现了微软的这个MSHTML库,最后发现在解析动态页面的时候它的表现实在是太差:在项目中需要像浏览器那样,执行JavaScri ...