According to P.J. Plauger
Its origins lie in the old
<std.h>
header we developed at Whitesmiths, Ltd. in the late 1970s. We used the typedef BYTES as the type of sizeof, to be sure we could count all the bytes in the largest declarable (or allocatable) object. X3J11 chosesize_t
to follow the*_t
convention that had begun to creep up in Posix.
Essentially, C needed a portable way to represent the sizes of objects
in memory. Before the size_t
came about, it was common practice to use
unsigned int
instead. K&R C book has a reference to size_t
on the Appendix
A (page 204).
From the man page, size_t
is defined as:
Used for a count of bytes. It is the result of the sizeof() operator.
It is an unsigned integer type capable of storing values in the range [0,
SIZE_MAX].
The SIZE_MAX
value is defined as:
/* Limit of `size_t' type. */
# if __WORDSIZE == 64
# define SIZE_MAX (18446744073709551615UL)
# else
# if __WORDSIZE32_SIZE_ULONG
# define SIZE_MAX (4294967295UL)
# else
# define SIZE_MAX (4294967295U)
# endif
# endif
In my machine I'm getting the value of 4294967295l
from the script below:
#include <stdint.h>
#include <stdio.h>
int main() {
printf("sizemax is: %ul", SIZE_MAX);
}
Apart from functions that deal with memory (alloc and company), the size_t
type is also used for array indexing.
Given that size_t
is a portable type, and it is unsigned by virtue, it is
a natural type for array indexing.
Besides that, size_t
is typically large enough to represent the maximum size
of an array that can be allocated in memory.
In other words, it is capable of holding the size of the largest object you can allocate. It is useful for indexing because this means it can index into the largest array you can allocate.
Some standard library function implementations use size_t
internally:
Also, using int
(as an alternative) for the index can cause an extra ASM
instruction on x86-64:
// ; zero-extending idx (in edx) is "free" by simply using rsi.
// get_index:
// movzx eax, BYTE PTR [rdi+rsi]
// ret
char get_index(char *ptr, size_t idx)
{
return ptr[idx];
}
// ; sign extending idx from 32 bits to 64 bits with movsx here.
// get_index:
// movsx rsi, esi
// movzx eax, BYTE PTR [rdi+rsi]
// ret
char get_index(char *ptr, int idx)
{
return ptr[idx];
}
size_t
is unsigned. Do not mingle arithmetic operations
between size_t
and other signed types. For example,#include <stdio.h>
int main() {
size_t foo = 10;
int bar = -20;
size_t foo_bar = foo + bar;
// This prints: "foo_bar is 18446744073709551606"
printf("foo_bar is %lu", foo_bar);
}
#include <stdio.h>
#include <stdint.h>
int main() {
size_t foo = (SIZE_MAX - 10);
int bar = 11;
size_t foo_bar = foo + bar;
// This prints: "foo_bar is 0"
printf("foo_bar is %lu", foo_bar);
}