Deutsch English Français Italiano |
<va275j$3d6tp$1@dont-email.me> View for Bookmarking (what is this?) Look up another Usenet article |
Path: ...!3.eu.feeder.erje.net!feeder.erje.net!weretis.net!feeder8.news.weretis.net!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail From: Andrey Tarasevich <andreytarasevich@hotmail.com> Newsgroups: comp.lang.c Subject: Re: size_t best practice Date: Tue, 20 Aug 2024 06:53:54 -0700 Organization: A noiseless patient Spider Lines: 72 Message-ID: <va275j$3d6tp$1@dont-email.me> References: <VdCcne2MOeshN1z7nZ2dnZfqnPWdnZ2d@brightview.co.uk> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit Injection-Date: Tue, 20 Aug 2024 15:53:56 +0200 (CEST) Injection-Info: dont-email.me; posting-host="595ca608e1cd2116537308d2a915e4c8"; logging-data="3578809"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/apUR3QF3XVKszMYudq+9i" User-Agent: Mozilla Thunderbird Cancel-Lock: sha1:05I2prsHAsA2LK6bOvDk/ir9p6w= In-Reply-To: <VdCcne2MOeshN1z7nZ2dnZfqnPWdnZ2d@brightview.co.uk> Content-Language: en-US Bytes: 3376 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. Another widely used idiom for this kind of iteration is for (size_t i = v->size; i-- > index;) v->_values[i + 1] = v->_values[i]; That's all. No need for any additional safeguards. > So is it considered best practice to use int, long, long long, or size_t, > in situations like these? It is not clear what you mean here. Use signed types everywhere, including container sizes? Or use signed types just for iteration? Anyway, the former is an iffy practice intended to replace learning with a safety blanket. The latter just leads to an unnecessary salad of types. -- Best regards, Andrey