Question

Which type in C should be used to represent the difference between two objects' sizes?

As size_t is unsigned, something like

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

obviously wouldn't be correct and it seems to me there's no real signed equivalent.

ptrdiff_t sounds kind of tempting, but

  1. like its name says it's for subtracting pointers.
  2. I've read that e.g. segmented platforms like DOS have a maximal object size of 64k which is representable by 16-bit. Far pointers, however, are composed of a 16-bit segment value and a 16-bit offset value. Wouldn't that make ptrdiff_t on such a platform 32-bit as well? If so, the difference between two objects in size only required 16-bit, but using ptrdiff_t would give you a 32-bit wide variable, making it sub-optimal.

So, what's a suitable, portable type for working with such a value?

Edit: I know about ssize_t, but it's

  1. not part of standard C.
  2. actually not intended for such use, but for returning either a size or a (negative) error value.
Was it helpful?

Solution 2

There isn't a standard datatype that's guaranteed to be 100% safe for what you're trying to do. For evidence, imagine if size_t is really just uint64_t, which is entirely possible. Then there's no standard C data type that is guaranteed to have a positive range that matches uint64_t and also handles negative values.

So the blunt answer to your question is "no datatype" (assuming strict adherence to standard C, which you seem to be desiring).

You're not clear on your use-case, however, and it's possible you may be able to take advantage of modular arithmetic to handle "negative" values. For example, the following code results in d2 being 4 because of modular arithmetic, allowing the code to act as if size_t were signed:

#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
}

Modular arithmetic may not be enough for you in your case, but for others it may.

OTHER TIPS

When I am really worried about overflow issues like that (especially when working in modular arithmetic where "negative" values wrap somewhere other than ~0) I just split it into two cases:

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

There is no signed C integer type that can hold all the values from a size_t value.

You could do this:

size_t diff = std::abs(static_cast <int> (sizeof (small_struct) - sizeof (big_struct)));
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top