Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What type for subtracting 2 size_t's?

Tags:

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.
like image 697
netcat Avatar asked Jan 07 '13 18:01

netcat


People also ask

What is size_ t data type?

size_t type is a base unsigned integer type of C/C++ language. It is the type of the result returned by sizeof operator. The type's size is chosen so that it can store the maximum size of a theoretically possible array of any type. On a 32-bit system size_t will take 32 bits, on a 64-bit one 64 bits.

Can you subtract Size_t?

Subtracting two std::size_t s will yield a new std::size_t † and its value will be determined by wrapping. In your example, assuming 64 bit size_t , a - b will equal 18446744073709551526 . This does not fit into an (commonly used 32 bit) int , so an implementation defined value is assigned to result .

Can you subtract a double from an int?

For example, it's totally okay to subtract an int from a double or float, since those data types will maintain the precision.

What is the purpose of size_ t in C?

It's a type which is used to represent the size of objects in bytes and is therefore used as the return type by the sizeof operator. It is guaranteed to be big enough to contain the size of the biggest object the host system can handle.


2 Answers

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. } 
like image 181
Ben Jackson Avatar answered Sep 18 '22 02:09

Ben Jackson


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.

like image 41
Cornstalks Avatar answered Sep 21 '22 02:09

Cornstalks