Always Design for C arrays — From subarray to range and back
C arrays are not range-checked, fixed-sized, and fast; just the way we like it.
Guess what, even variable-sized arrays are fixed-sized. A fixed-sized array is allocated, when its length reaches its capacity, another fixed-sized array of a higher size is allocated and the old data copied to the new array.
Its all fixed-sized. vector is a c-array, string is also a c-array.
Fixed-sized arrays are subarrays
Given the array declaration,
const size_t n = 256;
int buf[n];
The following pairs
| &buf[0], n | // entire array
| &buf[5], 2 | // subarray representing range [5,7) of range (0, 256)
are subarrays of array buf.
Assuming the entire array is filled with zero’s
fill(&buf[0], n, 0);
We can fill specific subarrays for example the subarray | &buf[5], 2 | with
fill(&buf[5], 2, 4);
where the function fill, is defined as
template <class T>
inline void
fill(T* f, int64_t n, const T& val) {
for (--n; n >= 0; --n) f[n] = val;
}
From Range to Subarray
A range is an arithmetic progression.
A range [i, j] is a sequence of integers i, i+1, . . ., j
A range [i, j) is a sequence of integers i, i+1, . . ., j-1
A range (i, j] is a sequence of integers i+1, . . ., j-1
A range (i, j) is a sequence of integers i+1, . . ., j-1
We consider the range [i, j) as default.
The size n of a range [i, j) can be gotten from the difference j-i.
Thus,
n = j-i
Given this, we can represent ranges with C subarrays.
The subarray with range [i, j) can be represented as
| &buf[i], j-i |
Consider the function below
template <class T>
inline void
incrementArrayByVal(T* f, int64_t n, const T& val) {
for (--n; n >= 0; --n) f[n] += val;
}
We can call it with subarray | &buf[i], j-i | as follows
increaseArrayByVal(&buf[i], j-i, val);