Let's have this array:
char arr[SIZE_MAX];
Note that many C implementations will reject that, SIZE_MAX
being larger than any array they can actually support. SIZE_MAX
is the maximum value of type size_t
, but that's not the same thing as the (implementation-dependent) maximum size of an object.
And I want to loop through it (and one past its last element):
for (i = 0; i <= sizeof(arr); i++)
What is the most adequate type for i?
There is no type available that we can be confident of being able to represent SIZE_MAX + 1
, and supposing that arr
indeed has size SIZE_MAX
, you need i
's type to be able to represent that value in order to avoid looping infinitely. Unless you want to loop infinitely, which is possible, albeit unlikely.
On the other hand, if we have
char arr[NOT_SURE_HOW_LARGE_BUT_LESS_THAN_SIZE_MAX];
then the appropriate type for i
is size_t
. This is the type of the result of the sizeof
operator, and if the only assumption we're making is that the object's size is smaller than SIZE_MAX
then size_t
is the only type we can be confident will serve the purpose.
If we can assume tighter bounds on the object's size, then it may be advantageous to choose a different type. In particular, if we can be confident that it is smaller than UINT_MAX
then unsigned int
may be a slightly more performant choice. Of course, signed types may be used for i
, too, provided that they can in fact represent all the needed values, but this may elicit a warning from some compilers.
size_t
if you have to ask, but using any other integer type which is capable to represent the whole range is not uncommon as well. You have other issues in the posted snippet though... – Inaei < sizeof arr
, not<=
. – Ulcerationsize_t
in Standard C, but clearly this valid snippet proves that if I used that type, I would have a problem, an infinitely lasting problem :). Standard C is broken for that reason, and that's the reason I accept POSIX for this (which is also broken, by the way). – Transmissioni <= sizeof(arr)
, and that's the reason I explicitly mentioned one past the last element. And that's the big problem of the question. – Transmissioni
inside the loop, then you will have an out-of-bounds access. Is your question about which type to use in this specific case where you don't access the one-past-the end element? – Inaesize_t
. – Arthro__int128
or an 80-bit or 128-bitlong double
then. – Ulceration&arr[i]
is dereferencing (it is equivalent to&(*(arr+i))
), so no, this code is not valid, but get your point. – InaeSIZE_MAX
, but a case where the size is given by asize_t
variable, the compiler will accept the code, and the program will break at run-time. – Transmission&*
considered equivalent to doing nothing? I'd have to look that part of the standard up again. – Colotomy*
with invalid pointer is UB. On the other hand - what you said. – Inaefor (i = sizeof(arr); i >= 0; i--)
(if the context allows it) – Transmissionlong double
) as Maxim said. – Transmissioni
can represent the size of the array, which is unlikely for the array size presented in the example. And if there were such a signed type, then its corresponding unsigned type would be perfectly suitable for the type ofi
in a forward iteration. – Vedi