Path: ...!news.misty.com!2.eu.feeder.erje.net!feeder.erje.net!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail From: Tim Rentsch Newsgroups: comp.lang.c Subject: Re: size_t best practice Date: Mon, 19 Aug 2024 09:43:38 -0700 Organization: A noiseless patient Spider Lines: 111 Message-ID: <86frr0cvk5.fsf@linuxsc.com> References: <20240818154013.00002ed7@yahoo.com> <86a5h9eagx.fsf@linuxsc.com> <20240819111303.00004a7a@yahoo.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Injection-Date: Mon, 19 Aug 2024 18:43:40 +0200 (CEST) Injection-Info: dont-email.me; posting-host="8e0243d997a628e731b4ff9e397b6328"; logging-data="3097322"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX192idwfS9ylhlL9XYJg/4uV4V9M8AzE2rM=" User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.4 (gnu/linux) Cancel-Lock: sha1:zNA4yhqckSp8+uuYbMByvZV9GaE= sha1:iA6fiVcUkoFlqif60CuH7i7btdU= Bytes: 6282 Michael S writes: > On Sun, 18 Aug 2024 15:23:58 -0700 > Tim Rentsch wrote: > >> Michael S writes: >> >>> On 18 Aug 2024 12:17:36 GMT >>> ram@zedat.fu-berlin.de (Stefan Ram) wrote: >>> >>>> Mark Summerfield wrote or quoted: >>>> >>>>> So is it considered best practice to use int, long, long long, or >>>>> size_t, in situations like these? >>>> >>>> In *cough*C++*cough* you could whip up a "SafeSize" class with >>>> a bulletproof "operator--", so you don't space on the check. >>>> You could still keep cranking out your code in what's basically C >>>> and just cherry-pick this one gnarly feature from that other >>>> language. >>>> >>>> SafeSize& operator--() >>>> { if( value == 0 ) >>>> { throw std::underflow_error("SafeSize decrement underflow"); } >>>> --value; >>>> return *this; } >>> >>> But that's not a desired behavior for people that want to write >>> downcounting for() loops in intuitive manner. >> >> Kind of a funny use of the word intuitive, for two reasons. >> >> The first is that writing for() loops, especially C for() loops, >> is learned behavior. There can be patterns that one is used to, >> but they are not "intuitive" in the usual sense of the word. >> >> The second is that people who program in C are accustomed to the >> idea of an asymmetry between counting up and counting down, >> because of how pointers work. It's okay to increment a pointer >> to one past the end of an array; it is not okay to decrement a >> pointer to one before the beginning of an array. Because of that >> the patterns for going forward and for going backward are just >> different. It seems odd to use the word "intuitive" to recognize >> that distinction. > > I would think that very large part of 'C' programmers ignores this > asymmetry. They are helped by the fact that 100% of production 'C' > compilers ignore it as well, which means that in practice code that > compares &arr[0] with &arr[-1] works as naively expected on all targets > that have flat memory model and far more often than not works on more > tricky targets as well. I long ago internalized the rule that C allows pointing one past the end of an array but does not allow pointing before the beginning. Certainly I don't expect that all C programmers respect that rule, but I do expect that most experienced C programmers will, especially given recent trends in aggressive optimizing, since the consequences of not doing so can be so dire. I also long ago developed the habit of not thinking about, at least most of the time, what is going on "under the hood" when compiling. A compiler is allowed to take advantage of how pointer arithmetic works, precisely because the compiler has privileged access to inside information. (It occurs to me now that this attitude might be humorously stated: Thinking "under the hood" Considered Harmful.) I don't think of either of those traits as ubiquitous, but I also don't think of them as special or unusual. Maybe that assumption isn't as generally apt as I think it is. >> Which is not to say I disagree with what you are saying. Actually >> I guess I'd have to say I'm not sure what it is you are saying. >> To my way of thinking the function above doesn't change the way I >> would write down-counting loops. It might be useful as a debugging >> aid aide, but nothing more (and an assert() is probably better). >> I think though that what you're saying is something else but I'm >> not sure what it is. > > Nothing fancy. Just an ability to write downcounting loops in a > way that I, obviously mistakenly, consider intuitive. > for (i = len-1; i >= 0; --i) I wouldn't say mistaken just because you used what might be a funny word choice (and not everyone would agree on that point). For example if you had used the phrase "in a natural way" I think most people would have understood it as you meant for the original. I'm just fussy about words. In many cases, or maybe even most cases, when there is a down counting loop the code looks cleaner (to be clear, to me) to start after the end than at the end. For example, the inner loop of an insertion sort: T e = elements[i]; for( j = i; j > 0 && before( e, elements[j-1] ); j-- ){ elements[j] = elements[j-1]; } elements[j] = e; The invariant is that j is the index of a "hole" that moves down the array. Again, my reaction doesn't mean that your way is wrong, or even bad. People get used to what they get used to. Maybe this relates to our attitudes about index signedness: I strongly prefer unsigned types for indexing, and you prefer, I think, signed types. Sometimes people prefer one choice over another just because it's what they are used to. For me personally the preference for unsigned index types is not one of those. But there can be value in having strong habits even if the habits came about accidentally rather than as a result of a considered conscious choice.