c/c++语言开发共享宏定义ARRAY_SIZE

在Google V8项目中读取globals.h时,我遇到了以下宏定义。

// The expression ARRAY_SIZE(a) is a compile-time constant of type // size_t which represents the number of elements of the given // array. You should only use ARRAY_SIZE on statically allocated // arrays. #define ARRAY_SIZE(a)  ((sizeof(a) / sizeof(*(a))) /  static_cast(!(sizeof(a) % sizeof(*(a))))) 

我的问题是后一部分: static_cast(!(sizeof(a) % sizeof(*(a))))) 。 我想到的一件事是:由于后一部分将始终求值为1 ,其类型为size_t ,因此整个表达式将被提升为size_t

如果这个假设是正确的,则会出现另一个问题:由于sizeof运算符的返回类型是size_t,为什么需要这样的推广? 以这种方式定义宏有什么好处?

    后一部分将始终计算为1,其类型为size_t,

    理想情况下,后面的部分将评估为bool (即true / false )并使用static_cast<> ,它将转换为size_t

    为什么这种促销是必要的? 以这种方式定义宏有什么好处?

    我不知道这是否是定义宏的理想方式。 但是,我发现的一个灵感来自注释: //You should only use ARRAY_SIZE on statically allocated arrays.

    假设,如果有人传递指针,那么struct (如果它大于指针大小)数据类型将失败。

     struct S { int i,j,k,l }; S *p = new S[10]; ARRAY_SIZE(p); // compile time failure ! 

    [注意:此技术可能不会显示int*char*任何错误。 int*

    正如所解释的那样,这是一种微弱的(*)尝试来保护宏不被指针(而不是真正的数组)使用,因为它不能正确地评估数组的大小。 这当然源于这样一个事实,即宏是基于文本的纯操作,并且没有AST的概念。

    由于问题也标记为C ++,我想指出C ++提供了一种类型安全的替代方案:模板。

     #ifdef __cplusplus template  struct ArraySizeHelper { char _[N]; }; template  ArraySizeHelper makeArraySizeHelper(T(&)[N]); # define ARRAY_SIZE(a) sizeof(makeArraySizeHelper(a)) #else # // C definition as shown in Google's code #endif 

    或者,很快就能使用constexpr

     template  constexpr size_t size(T (&)[N]) { return N; } 

    但是我最喜欢的编译器(Clang)仍然没有实现它们:x

    在这两种情况下,由于函数不接受指针参数,如果类型不正确,则会出现编译时错误。

    (*)微弱,因为它不适用于对象大小是指针大小的除数的小对象。


    只是演示它是编译时的值:

     template  void print() { std::cout << N << "n"; } int main() { int a[5]; print(); } 

    在IDEONE上查看它。

    如果sizeof(a) / sizeof(*a)有一些余数(即a不是*a的整数),则表达式将计算为0 ,编译器会在编译时给出 除错

    我只能假设宏的作者过去曾被未通过该测试的东西烧毁。

    在Linux内核中,宏被定义为(特定于GCC):

     #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)) 

    第二部分希望确保sizeof( a )可以被sizeof( *a )整除。

    因此(sizeof(a) % sizeof(*(a)))部分的大小。 如果它可以被整除,则表达式将被计算为0 。 来了! 部分 – !(0)将给出true 。 这就是演员需要的原因。 实际上,这不会影响大小的计算,只需添加编译时检查。

    由于它是编译时,如果(sizeof(a) % sizeof(*(a)))不为0 ,则0分区的编译时错误。

    需要了解更多c/c++开发分享宏定义ARRAY_SIZE,也可以关注C/ C++技术分享栏目—计算机技术网(www.ctvol.com)!

      以上就是c/c++开发分享宏定义ARRAY_SIZE相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。

      本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

      ctvol管理联系方式QQ:251552304

      本文章地址:https://www.ctvol.com/c-cdevelopment/979892.html

      (0)
      上一篇 2021年12月13日
      下一篇 2021年12月13日

      精彩推荐