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