Какой тип для вычитания 2 size_t?

Какой тип в C следует использовать для представления разницы между размерами двух объектов?

Поскольку size_t не имеет знака, что-то вроде

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

очевидно, не было бы правильным, и мне кажется, что нет реального подписанного эквивалента.

ptrdiff_t звучит соблазнительно, но

  • как и его имя, говорит об этом для вычитания указателей.
  • Я читал, например, сегментированные платформы, такие как DOS, имеют максимальный размер объекта 64k, который представляется 16-разрядным. Однако дальние указатели состоят из 16-разрядного значения сегмента и 16-разрядного значения смещения. Разве это не сделало бы ptrdiff_t на такой платформе 32-битной? Если это так, разница между двумя объектами в размере требует только 16 бит, но использование ptrdiff_t даст вам 32-битную ширину переменной, что делает ее не оптимальной.

Итак, какой подходящий переносимый тип для работы с таким значением?

Edit: Я знаю о ssize_t, но это

  • не является частью стандартного C.
  • на самом деле не предназначен для такого использования, но для возврата значения размера или (отрицательного) значения.

Ответ 1

Нет стандартного типа данных, который гарантированно будет на 100% безопасным для того, что вы пытаетесь сделать. Для доказательства предположите, что size_t действительно просто 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
}

Модульная арифметика может быть недостаточно для вас в вашем случае, но для других это может быть.

Ответ 2

Когда я действительно беспокоюсь о проблемах с переполнением (особенно при работе в модульной арифметике, где "отрицательные" значения переносятся где-то, кроме ~0), я просто разделил его на два случая:

if (a > b) {
    size_t diff = a - b;
} else {
    size_t diff = b - a;
    // code here subtracts diff rather than adds it, etc.
}

Ответ 3

Нет целочисленного типа C, который может содержать все значения из значения size_t.

Ответ 4

Вы можете сделать это:

size_t diff = std::abs(static_cast <int> (sizeof (small_struct) - sizeof (big_struct)));