23

应该使用 C 中的哪种类型来表示两个对象大小之间的差异?

如未size_t签名,类似

size_t diff = sizeof (small_struct) - sizeof (big_struct);

显然是不正确的,在我看来,没有真正的签名等价物。

ptrdiff_t听起来有点诱人,但是

  1. 就像它的名字所说的那样,它是用来减去指针的。
  2. 我已经读过,例如像 DOS 这样的分段平台具有 64k 的最大对象大小,可以用 16 位表示。然而,远指针由一个 16 位段值和一个 16 位偏移值组成。在这样的平台上不是也可以ptrdiff_t使用 32 位吗?如果是这样,两个对象之间的大小差异只需要 16 位,但使用 ptrdiff_t 会给你一个 32 位宽的变量,使其不是最佳的。

那么,使用这种值的合适的便携式类型是什么?

Edit: 我知道 ssize_t,但它是

  1. 不是标准 C 的一部分。
  2. 实际上不是用于这种用途,而是用于返回大小或(负)错误值。
4

4 回答 4

18

当我真的担心这样的溢出问题时(尤其是在模算术中,“负”值包含在 以外的某个地方时~0)我只是将其分为两种情况:

if (a > b) {
    size_t diff = a - b;
} else {
    size_t diff = b - a;
    // code here subtracts diff rather than adds it, etc.
}
于 2013-01-07T19:07:26.373 回答
9

对于您正在尝试做的事情,没有一种标准数据类型可以保证 100% 安全。作为证据,想象 ifsize_t真的是 just uint64_t,这是完全可能的。然后没有标准的 C 数据类型可以保证具有匹配的正范围uint64_t并处理负值。

因此,对您的问题的直截了当的回答是“没有数据类型”(假设严格遵守您似乎想要的标准 C)。

但是,您不清楚您的用例,并且您可能能够利用模运算来处理“负”值。例如,以下代码d2由于模算术而导致4,允许代码像size_t签名一样工作:

#include <stdio.h>
#include <stdint.h>

int main()
{
    size_t d1 = sizeof(int32_t) - sizeof(int64_t);
    size_t d2 = sizeof(int64_t) + d1; // Add difference (even if d1 is "negative"*)

    printf("d1: %zu\n", d1);
    printf("d2: %zu\n", d2);

    return 0;
    // * By "negative" I mean that d1 would be negative if size_t were signed
}

在您的情况下,模块化算术可能对您来说还不够,但对其他人来说可能。

于 2013-01-07T19:11:42.423 回答
2

没有可以保存一个size_t值的所有值的有符号 C 整数类型。

于 2013-01-07T19:10:45.793 回答
-2

你可以这样做:

size_t diff = std::abs(static_cast <int> (sizeof (small_struct) - sizeof (big_struct)));
于 2014-03-22T16:35:44.373 回答