Какой тип для вычитания 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)));