What's wrong with loops and arrays?
Unrolling loops does have a disadvantage: It makes the code bigger. Bigger code means more memory accesses to fetch the code, and since memory access is slow, your code could end up being slower. Also, the Intel cpus preprocess the fetched code and turn them into uOps (micro ops) which are then scheduled and executed. The CPU has a cache of these uOps so it only decodes instructions that aren't already in the cache. So, an unrolled loop will fill up the cache and cause other code to bumped out. Smaller code is generally better.
As for arrays, I'm not sure how you'd get rid of them.
So, if you had:
struct TextureUnit
{
// some texture unit data
}
TextureUnit units [number_of_units];
for (int i = 0 ; i < number_of_units ; ++i)
{
callfunction (units [i].someparams);
}
it might be better to do:
for (TextureUnit *i = unit ; i < &unit [number_of_units] ; ++i)
{
callfunction (i->someparams);
}
but you'd need to see what the compiler is generating in the optimised build to be sure it actually gives any advantages.
I think this might be classed as a 'micro-optimisation', so I wouldn't really be worried about it unless you can prove it really is a bottleneck. Remember - profile the code, don't just guess.