What type for array index in C99 should be used? It have to work on LP32, ILP32, ILP64, LP64, LLP64 and more. It doesn’t have to be a C89 type.
I have found 5 candidates:
size_tptrdiff_tintptr_t/uintptr_tint_fast*_t/uint_fast*_tint_least*_t/uint_least*_t
There is simple code to better illustrate problem. What is the best type for i and j in these two particular loops. If there is a good reason, two different types are fine too.
for (i=0; i<imax; i++) {
do_something(a[i]);
}
/* jmin can be less than 0 */
for (j=jmin; j<jmax; j++) {
do_something(a[j]);
}
P.S.
In the first version of question I had forgotten about negative indexes.
P.P.S.
I am not going to write a C99 compiler. However any answer from a compiler programmer would be very valuable for me.
Similar question:
- size_t vs. uintptr_t
The context of this question if different though.
I almost always use
size_tfor array indices/loop counters. Sure there are some special instances where you may want signed offsets, but in general using a signed type has a lot of problems:The biggest risk is that if you’re passed a huge size/offset by a caller treating things as unsigned (or if you read it from a wrongly-trusted file), you may interpret it as a negative number and fail to catch that it’s out of bounds. For instance
if (offset<size) array[offset]=foo; else error();will write somewhere it shouldn’t.Another problem is the possibility of undefined behavior with signed integer overflow. Whether you use unsigned or signed arithmetic, there are overflow issues to be aware of and check for, but personally I find the unsigned behavior a lot easier to deal with.
Yet another reason to use unsigned arithmetic (in general) – sometimes I’m using indices as offsets into a bit array and I want to use %8 and /8 or %32 and /32. With signed types, these will be actual division operations. With unsigned, the expected bitwise-and/bitshift operations can be generated.