Can sizeof(size_t) be less than sizeof(int)?
Asked Answered
B

2

6

Can sizeof(size_t) be less than sizeof(int)?

Do the C and/or C++ standards guarantee that using unsigned int for array indexing is always safe?

Bananas answered 21/1, 2020 at 1:42 Comment(11)
Why wouldn't using an unsigned int be safe? Array indexes can't be negative. Are you ever planning on having so many array elements as to overflow an unsigned int? It is technically possible for sizeof(size_t) to be more than sizeof(int) (ie, if size_t is unsigned long long on a 64bit system), but I doubt you will ever see it be less.Nethermost
@RemyLebeau I've seen some people from Java world thinking that array indices must be int. Maybe NoSkill is confused similarly?Ezzo
@UnmannedPlayer that is because Java doesn't have unsigned types, like C and C++ do. Arrays in Java have lengths represented by intNethermost
I think you're misunderstanding the question. He's wondering whether the range of unsigned int might be too large. e.g. size_t == unsigned charZoezoeller
@RemyLebeau: Array indexes can be negative. For example: int arr[10]; int *ptr = arr+5; ptr[-5] = 0; is perfectly valid.Faline
At least POSIX expects size_t to be Unsigned integer type of the result of the sizeof operator.Ezzo
@UnmannedPlayer That is part of the C++ standard, that is not limited to POSIXNethermost
@KeithThompson That is not using a negative array index, though. That is accessing arr[0] using pointer arithmetic. arr[-1] is not valid, for instance. Neither would ptr[-6] in your example.Nethermost
@RemyLebeau: The [] operator is defined in terms of pointer arithmetic. The pointer is required to point to an element of an array object (including a non-array object that's treated as a 1-element array). If by "array index" you mean the index relative to the base of the array object into which the pointer points, then you're right, but the standard doesn't describe it in those terms.Faline
@KeithThompson: The C standard does not use “array index” at all. The phrase is just plain words, which, on the face of them, describe an index into an array. By applying it to subscripts used with pointers, you are giving it a new and different meaning.Attaboy
@UnmannedPlayer In any sanely written class with array like behavior, array indices are signed integers: array::operator[](int) not array::operator[](unsigned)Uncommunicative
F
11

Yes, sizeof(size_t) can, in principle, be less than sizeof(int). I don't know of any implementations where this is true, and it's likely that there are none. I can imagine an implementation with 64-bit int and 32-bit size_t.

But indexing an array with unsigned int is safe -- as long as the value of the index is within the bounds imposed by the length of the array. The argument to the [] operator is merely required to be an integer. It's not converted to size_t. It's defined in terms of pointer arithmetic, in which the + operator has one argument that's a pointer and another argument that is of any integer type.

If unsigned int is wider than size_t, then an unsigned int index value that exceeds SIZE_MAX will almost certainly cause problems because the array isn't that big. In C++14 and later, defining a type bigger than SIZE_MAX bytes is explicitly prohibited (3.9.2 [compound.types] paragraph 2; section 6.9.2 in C++17). In earlier versions of C++, and in all versions of C, it isn't explicitly prohibited, but it's unlikely that any sane implementation would allow it.

Faline answered 21/1, 2020 at 1:47 Comment(6)
Moreover, if the sizes of objects are truly limited to values that can be represented by size_t, so that the original question is meaningful, an index of type size_t can express at least one value that is out of bounds for every array. For substantially all arrays actually observed in real programs, a size_t can express very many out of bounds indexes. Its association with the maximum possible size of objects, where that exists, does not make it safer for indexing.Margetmargette
"An implementation that supports arrays of more than SIZE_MAX elements will almost certainly make size_t bigger." is unclear. Did you mean "An implementation that supports arrays of more than UINT_MAX elements ..." ? An array, like any object, is size SIZE_MAX or less. I suspect this in a C++ thing.Derbyshire
@chux-ReinstateMonica No, I meant SIZE_MAX. C has no explicit requirement that objects can't be bigger than SIZE_MAX bytes. A C implementation could, for example, have 32-bit size_t but allow 2<sup>33</sup>-element arrays -- then sizeof obj could overflow. The obvious solution would be for such an implementation to make its size_t big enough to hold the size of any object. Apparently this doesn't apply to C++14 and later.Faline
Keith, Thanks. "The sizeof operator yields the size (in bytes) of its operand" can also be read as "C has no explicit requirement that objects can be bigger than SIZE_MAX. I'll grant that this is not explicit either way about can/can't be bigger... But the implication, IMO is cannot. Looks like a good SO question unto itself.Derbyshire
@chux-ReinstateMonica It would be nice IMHO if that were stated explicitly. But I don't see how an implementation with 32-bit size_t that allows 2**33-element arrays would violate any requirement in the C (or C++ prior to 2014) standard. Possibly it's a case the authors didn't think of. IMHO sizeof ... can overflow just like any other arithmetic expression.Faline
@chux-ReinstateMonica Which presumably is why C++14 added "Constructing a type such that the number of bytes in its object representation exceeds the maximum value representable in the type std::size_t is ill-formed." (3.9.2 [basic.compound] paragraph 3). This wording is not in C++11 (or in any edition of ISO C).Faline
D
4

[C answer]

Can sizeof(size_t) be less than sizeof(int)?

Yes. The size of size_t can be less, more or the same as int as their relative sizes/ranges are not specified in C - only their minimum _MAX values: 65535, 32767.

IMO, sizeof(size_t) < sizeof(int) is a unicorn. Theoretical, but not seen.

Code could use the following to detect such beasties.

#include <limits.h>
#include <stddef.h>
#if SIZE_MAX < UINT_MAX
  #error Unexpected small size_t
#endif

Do the C and/or C++ standards guarantee that using unsigned int for array indexing is always safe?

In C, No.

Examples: A small array may only tolerate the indexes of [0 ... 2] - regardless of the type of the index - not the entire range of unsigned. A huge array may be index-able [0 ... UINT_MAX*42ull] and so an unsigned cannot represent all valid indexes.

A size_t is wide enough to index all arrays.

Derbyshire answered 21/1, 2020 at 10:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.