Reputation: 17427
Can I trust sizeof(size_t) <= sizeof(unsigned long int)
is always true, according to C89 standard?
i.e., I will not loos value if I use a unsigned long
where size_t
is expected and vice-versa.
Upvotes: 3
Views: 703
Reputation: 735
According to the 1999 ISO C standard (C99), size_t is an unsigned integer type of at least 16 bit (see sections 7.17 and 7.18.3).
So sizeof(size_t) <= sizeof(unsigned long int)
is true, but sizeof(size_t) > sizeof(unsigned long int)
is not true and can lead to data loss. For instance:
size_t a = b;
may cause data loss if b
is an unsigned long int
since its value can be grater than an size_t
can hold.
Upvotes: 2
Reputation: 4433
Perhaps the best explanation of what happens with size_t
and integer types in C89 is the rationale document of it. Read carefully the section 3.4.4 of this document:
Sizeof and size_t for C89 (rationale)
The 3rd paragraph says that:
The type of sizeof, whatever it is, is published (in the library header ) as size_t, since it is useful for the programmer to be able to refer to this type. This requirement implicitly restricts size_t to be a synonym for an existing unsigned integer type, thus quashing any notion that the largest declarable object might be too big to span even with an unsigned long.
This means that, for the concern of C89, in general size_t
is the same as a preexisting unsigned
integer type, what in C89 implies one of the unsigned char, unsigned short, unsigned int, unsigned long
.
In particular, every value of type size_t
is in the range of unsigned long
.
By reading the specifications of the standard C89, you can see also that sizeof(size_t)<=sizeof(long)
.
Now, the situation in C99 is a little different. This standard says that:
size_t
is an unsigned integer type. size_t
[...] should not have an integer conversion rank greater than that of signed long int
6.2.5 par. 8 For any two integer types with the same signedness and different integer conversion rank (see 6.3.1.1), the range of values of the type with smaller integer conversion rank is a subrange of the values of the other type.
Since the integer conversion rank of signed long int
is the same that unsigned long int
, this implies that the range of values of size_t
is contained in the range of values of unsigned long int
.
But the item 3 in the list above left the door open to exceptions to this rule.
So, we can only say that is highly intended that an implementation makes the values of size_t
hold in the range of the unsigned long int
. But we cannot be completely sure.
If you want to be sure, you can do the following procedure to check your system:
<limits.h>
and <stdint.h>
in order to access the information about integer types for your implementation. ULONG_MAX
(from <limits.h>
) and SIZE_MAX
(from <stdint.h>
).A short program would be this:
#include <stdio.h>
#include <limits.h>
#include <stdint.h>
int main(void) {
printf("Is the range of size_t containd in that of unsigned long?\n\n");
if (SIZE_MAX <= ULONG_MAX)
printf("Yes");
else
printf("No");
return 0;
}
Upvotes: 6