int vs size_t vs long

124 Views Asked by At

I have been seeing a lot of people lately say that you should use size_t instead of int. But what is the difference? Is it always better? Or are there situations for int, and situations for size_t? Or maybe size_t is similar to long? When should I use int, when should I use size_t, and when should I use long?

2

There are 2 best solutions below

0
chux - Reinstate Monica On BEST ANSWER

Is it (size_t) always better?

Usually


  • int math may fail size calculation that woks with size_t math.
    int r = rand();
    int c = rand();
    char *ptr1 = malloc(r * c); // Overflow possible
    char *ptr2 = malloc((size_t) 1 * r*c); // Overflow possible, yet less likely.

  • int range may be (and often is) less than size_t range.

When sizeof some_object exceeds INT_MAX, following code will certainly lead to errors.

int sz = sizeof some_object;  // Problem when size is large.
// Good as
size_t sz = sizeof some_object;  // No problem for all sizeof return values.

  • unsigned range may be less than size_t range.

String lengths may be longer than UINT_MAX

unsigned sz = strlen(pointer_to_a_string); // Problem when length is large.
// Good as
size_t sz = strlen(pointer_to_a_string); // No problem for all values from strlen().

  • size_t is an unsigned type, so avoid tests like size >= 0, size < 0, size == -1.

When code decrements the size below zero, we have issues.

// Compare
int isize = sizeof object;  // Bad as size may exceed INT_MAX
while (isize >= 0) {
  ...
  isize--;
}
size_t usize = sizeof object;
while (usize >= 0) {  // Bad as usize >= 0 is _always_ true
  ...
  usize--;
}

Instead re-work code in some fashion.

size_t usize = sizeof object;
do {
  ...
} while (usize-- > 0):
6
Lundin On

The main reason is self-documenting code. size_t is used exclusively for the purpose of describing the size of things.

But there are also some practical advantages of using size_t over int:

  • Array/object sizes are always unsigned and positive and should therefore be represented by an unsigned type. Using a negative value as array size is always a bug. Using a negative value as array index is also problematic since it is hard to read, probably also a bug.

  • int may overflow in certain scenarios when it is not large enough to contain a requested size. size_t is guaranteed to be at least large enough to contain the size of the largest supported object.

  • int may be subject to implicit promotion in case it is mixed with larger operands in the same expression.

  • int is further problematic if used to represent addresses, or if used to store the results of pointer arithmetic. Here there are other more suitable types like uintptr_t and ptrdiff_t respectively.

size_t therefore provides better compatibility with the sizeof operator as well as various standard library functions (like for example strlen). Mostly these problems get exposed when porting sloppily written code using int into 64 bit systems.

However size_t is not without problems either, since its size is unknown. In certain scenarios like hardware-related programming, the fixed width types in stdint.h might be more suitable to use than size_t, or you might risk getting a type that is too large.

Some old C libs also had bad compliance and weren't properly supporting %zu for the printf/scanf family of functions.