代码之家  ›  专栏  ›  技术社区  ›  Prasoon Saurav

使用指针算法计算类型大小的另一种方法

  •  8
  • Prasoon Saurav  · 技术社区  · 14 年前

    以下代码是否100%可移植?

    int a=10;
    size_t size_of_int = (char *)(&a+1)-(char*)(&a); // No problem here?
    
    std::cout<<size_of_int;// or printf("%zu",size_of_int);
    

    附笔 :此问题仅用于学习目的。所以请不要这样回答 Use sizeof()

    9 回复  |  直到 14 年前
        1
  •  13
  •   fredoverflow    14 年前

    从ANSI-ISO-IEC 1488—2003,P.78(C++ 03):

    “75)另一种接近指针的方法 算术是第一个转换 指向字符指针的指针:在 这个方案的积分值 表达式加减 转换后的指针是第一个 乘以对象的大小 最初指的是,和 结果指针转换回 原始类型。指向指针 减法的结果 性格差异 指针也被 最初指向的对象的大小 “

    这似乎表明指针差等于对象大小。

    如果我们从增加指向标量a的指针并将a转换为数组中删除了ub'ness:

    int a[1];
    size_t size_of_int = (char*)(a+1) - (char*)(a);
    
    std::cout<<size_of_int;// or printf("%zu",size_of_int);
    

    那么这个看起来不错。有关对齐要求的条款与脚注一致,如果对齐要求总是可以被对象的大小整除。

    更新: 有趣。正如大多数人可能知道的,gcc允许将类型的显式对齐指定为扩展。但我不能用它破坏op的“sizeof”方法,因为gcc拒绝编译它:

    #include <stdio.h>
    
    typedef int a8_int __attribute__((aligned(8)));
    
    int main()
    {
     a8_int v[2];
    
     printf("=>%d\n",((char*)&v[1]-(char*)&v[0]));
    }
    

    消息是 error: alignment of array elements is greater than element size .

        2
  •  4
  •   Kirill V. Lyadvinsky    14 年前

    &a+1 将根据C++标准5.7/5导致未定义的行为:

    当将具有整型的表达式添加到指针或从指针中减去时,结果的类型为 指针操作数。<……>如果指针操作数和结果都指向同一数组对象的元素,或者指向数组对象最后一个元素的一个元素,则计算结果不应产生溢出; 否则,行为是未定义的 .

    &A+ 1 是否符合5.7/4:

    对于这些运算符,指向非数组对象的指针的行为与指向第一个对象的指针的行为相同 长度为1的数组的元素,其元素类型为对象的类型。

    这意味着5.7/5可以不使用ub。最后,5.7/6中的75条评论为 @Luther Blissett 在他的回答中指出,问题中的代码是有效的。


    在生产代码中应该使用 sizeof 相反。但是C++标准并不能保证 sizeof(int) 将在每个32位平台上生成4个。

        3
  •  2
  •   h2stein    14 年前

    不,这个代码在每个平台上都不能像您期望的那样工作。至少在理论上,可能有一个平台,例如24位整数(=3字节)但32位对齐。对于(旧的或更简单的)平台,这样的对准并非不典型。然后,代码将返回4,但sizeof(int)将返回3。

    但我不知道真正的硬件是这样的。实际上,您的代码将在大多数或所有平台上工作。

        4
  •  2
  •   Michael F    14 年前

    它不是100%可移植的,原因如下:

    1. 编辑:你最好用 int a[1]; 然后 a+1 最终有效。
    2. &对寄存器存储类的对象调用未定义的行为。
    3. 如果对齐限制大于或等于 int 类型, size_of_int 不包含正确答案。

    免责声明:

    我不确定上面是否有C++。

        5
  •  1
  •   Ana Betts    14 年前

    为什么不只是:

    size_t size_of_int = sizeof(int);
    
        6
  •  1
  •   Henk Holterman    14 年前

    它可能是实现定义的。

    我可以想象一个(假设的)系统,其中sizeof(int)小于默认对齐。

    这样说才安全 size_of_int >= sizeof(int)

        7
  •  0
  •   sharptooth    14 年前

    上面的代码可以方便地计算 sizeof(int) 在目标平台上,但后者是实现定义的——您将在不同的平台上获得不同的结果。

        8
  •  0
  •   wilx    14 年前

    是的,它给了你相当于 sizeof(a) 但使用 ptrdiff_t 而不是 size_t 类型。

        9
  •  0
  •   Community Michael Schmitz    7 年前

    有一场关于 similar question .

    查看评论 my answer 对于这个问题,有些人提出了这样的问题:为什么这不仅是不可移植的,而且是标准中未定义的行为。