代码之家  ›  专栏  ›  技术社区  ›  Phil Miller

对size_t(即`-size(struct foo)`)的否定应该如何处理?

  •  12
  • Phil Miller  · 技术社区  · 16 年前

    -(sizeof(struct foo))
    

    即a的否定 size_t ,当编译器看到这一点时,我不清楚C和C++标准对编译器的要求是什么。具体来说,从这里和其他地方看, sizeof size_t 。在否定无符号整数时,我找不到任何明确的行为参考。有没有,如果有,是什么?

    6 回复  |  直到 16 年前
        1
  •  21
  •   John Millikin    16 年前

    n -即,对于任何溢出或下溢,它都会“环绕”。对于ISO C++,这是3.9.1[基本。基本]/4:

    unsigned n 哪里 n 是该特定大小的整数的值表示中的位数。

    ...

    41)这意味着无符号算术不会溢出,因为结果无法用得到的无符号整数表示 类型被缩减为比结果无符号整数所能表示的最大值大1的数字的模 类型。

    对于ISO C(99),它是6.2.5/9:

    SIZE_MAX - (sizeof(struct foo)) + 1 .


    在ISO 14882:2003 5.3.1.7中:

    […]无符号的负数 n n 是中的位数 推进操作数。……的类型 操作数。

        2
  •  2
  •   John Millikin    16 年前

    http://msdn.microsoft.com/en-us/library/wxxx8d2t%28VS.80%29.aspx

    无符号量的一元否定 通过减去该值来执行 2的操作数 n ,其中n是 二补算术。在其他 处理器,否定算法 可能会有所不同。)

    换句话说,确切的行为将是特定于架构的。如果我是你,我会避免使用这种奇怪的构造。

        3
  •  2
  •   Ste    16 年前

    否定一个无符号数对于在字上传播lsb以形成后续位操作的掩码非常有用。

        4
  •  1
  •   Chad Simpkins    16 年前

    我唯一能想到的就是错得让我头疼。..

    size_t size_of_stuff = sizeof(stuff);
    
    if(I want to subtract the size)
        size_of_stuff = -sizeof(stuff);
    
    size_t total_size = size_of_stuff + other_sizes;
    

        5
  •  1
  •   Phil Miller    16 年前

    current C++ draft standard 第5.3.1节第8句:

    一元函数的操作数 - 运算符应具有算术或枚举类型,其结果是其操作数的否定。积分提升是对积分或枚举操作数执行的。无符号量的负数是通过从2中减去其值来计算的 n ,其中n是升级操作数中的位数。结果的类型是升级操作数的类型。

    用户@outis在评论中提到了这一点,但我会把它放在答案中,因为outis没有。如果outis回来回答,我会接受。

        6
  •  1
  •   Keith Thompson    10 年前

    size_t 是一种实现定义的无符号整数类型。

    否定a size_t 价值 可能 为您提供类型的结果 size_t 具有通常的无符号模行为。例如,假设 size_t 为32位 sizeof(struct foo) == 4 那么 -sizeof(struct foo) == 4294967292 ,或2 4.

    - 操作员应用 (C) 或 (C++)(它们本质上是一样的)到它的操作数。如果 size_t 宽度至少与 int size_t 整数 size_t INT_MAX >= SIZE_MAX - 从“提升” size_t 整数 在这种不太可能的情况下, -sizeof(struct foo) == -4 .

    如果将该值重新分配给 size_t size_t SIZE_MAX-4 你期望的价值。但如果没有这样的转换,你会得到一些令人惊讶的结果。

    现在我从来没有听说过这样的实现 size_t 整数 ,所以你不太可能遇到这种情况。但这里有一个测试用例,使用 unsigned short 作为假想狭窄的替代品 size_t 类型,说明潜在的问题:

    #include <iostream>
    int main() {
        typedef unsigned short tiny_size_t;
        struct foo { char data[4]; };
        tiny_size_t sizeof_foo = sizeof (foo);
        std::cout << "sizeof (foo) = " << sizeof (foo) << "\n";
        std::cout << "-sizeof (foo) = " << -sizeof (foo) << "\n";
        std::cout << "sizeof_foo = " << sizeof_foo << "\n";
        std::cout << "-sizeof_foo = " << -sizeof_foo << "\n";
    }
    

    short ,32位 整数 ,以及64位 size_t )是:

    sizeof (foo) = 4
    -sizeof (foo) = 18446744073709551612
    sizeof_foo = 4
    -sizeof_foo = -4
    
    推荐文章