Sujet : Re: size_t best practice
De : tr.17687 (at) *nospam* z991.linuxsc.com (Tim Rentsch)
Groupes : comp.lang.cDate : 22. Aug 2024, 09:31:01
Autres entêtes
Organisation : A noiseless patient Spider
Message-ID : <86ed6h9cxm.fsf@linuxsc.com>
References : 1 2
User-Agent : Gnus/5.11 (Gnus v5.11) Emacs/22.4 (gnu/linux)
Andrey Tarasevich <
andreytarasevich@hotmail.com> writes:
On 08/18/24 1:03 AM, Mark Summerfield wrote:
>
However, this means I have to be very careful never to decrement a
size_t of value 0, since, e.g., size_t size = 0; size--; results in
size == 18446744073709551615.
>
That's a completely incorrect conclusion. There's nothing wrong
with decrementing a 0 of type `size_t`. It results in perfectly
defined behavior. It produces a `(size_t) -1` value.
>
For example, iteration all the way to 0 can be idiomatically
implemented as
>
for (some_unsigned_type i = size; (some_unsigned_type) i != -1; --i)
...
>
This will work, even though it will eventually decrement a zero
value. If you are sure that the type is "large" (e.g. `int` or
larger), then the cast is unnecessary
>
for (some_unsigned_type i = size; i != -1; --i)
...
>
(Note, BTW, that it also works perfectly for signed index types.)
>
>
So I need to guard against this. Here is an example I'm using
(without the assert()s):
>
void vec_insert(vec* v, size_t index, void* value) {
if (v->_size == v->_cap) {
vec_grow(v);
}
for (size_t i = v->_size - 1; i >= index; --i) {
v->_values[i + 1] = v->_values[i];
if (!i) // if i == 0, --i will wrap!
break;
}
v->_values[index] = value;
v->_size++;
}
>
No, that's rather weird and unnecessarily overwrought way to guard
against this.
>
We can immediately apply the pattern I demonstrated above to this
and get
>
for (size_t i = v->_size - 1; i != index - 1; --i)
v->_values[i + 1] = v->_values[i];
>
Done. No need for an extra safeguard.
Better (please ignore cosmetic layout differences):
for( size_t i = v->_size; i > index; i-- ){
v->_values[i] = v->_values[i-1];
}