Path: csiph.com!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!eternal-september.org!.POSTED!not-for-mail From: Keith Thompson Newsgroups: comp.lang.c Subject: Re: Loops (was Re: do { quit; } else { }) Date: Wed, 16 Apr 2025 17:47:49 -0700 Organization: None to speak of Lines: 87 Message-ID: <87mscfzk96.fsf@nosuchdomain.example.com> References: <20250413072027.219@kylheku.com> <20250415053852.166@kylheku.com> <20250416142925.663@kylheku.com> MIME-Version: 1.0 Content-Type: text/plain Injection-Date: Thu, 17 Apr 2025 02:47:49 +0200 (CEST) Injection-Info: dont-email.me; posting-host="ce66778584175375d620efc7d3b77de7"; logging-data="3570250"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/SOaQU/NO7JsykFoZXCrz4" User-Agent: Gnus/5.13 (Gnus v5.13) Cancel-Lock: sha1:ngW22dUKb0JxdfTYtgLxNC98os8= sha1:KIE9Ul/2iqWwSkPQiheac2m/hmI= Xref: csiph.com comp.lang.c:392639 bart writes: > On 16/04/2025 22:43, Kaz Kylheku wrote: [...] >> Hey Bart, how would you handle a loop like >> do x = m to n ... >> where m and n are not known until run time, and may be the >> extreme values of the type? Like C's INT_MIN and INT_MAX, respectively, >> where x is of type int. >> Because in this loop, x takes on every possible value of the type, >> we cannot have a loop guard which prevents entry of the loop body >> based on solely the value of x. > > I'm not exactly sure what you are asking. [...] > However, this languages evaluates using 64 bits. Perhaps this loop may > demonstrate the issues better: > > for i in i64.bounds do > > However, I would estimate it would take 190 years to finish. > > I assume you're thinking of C which uses i32 and where comparisons > near the extreme values of the type are problemetical. [...] "C which uses i32"? I'm going to guess that what you meant by that is that many, perhaps most, C implementations have 32-bit int. Of course the language doesn't specify that, and of course you can use expressions of any type you like in a C for loop. > my language: > > for i in i64.max-10 .. i64.max do println i > > which doesn't stop (u64 is OK however). That doesn't worry me too > much, I can just add a Note to the language spec warning of UB when a > for-loop bound is at the limits of the type. Where all sorts of other > stuff can happen because of how values wrap. And C's for loop has the same issue, though of course you don't need to resort to 64-bit arithmetic to demonstrate it: for (int i = INT_MAX-10; i <= INT_MAX; i++) { printf("%d\n", i); } This will cause a signed integer overflow and undefined behavior when i has reached INT_MAX, and the comparison `i <= INT_MAX` might even be optimized away. (Ada's for loop, for example, doesn't have this issue. The compiler is required to generate whatever code is necessary to make the equivalent loop iterate exactly 11 times. Ada's for loops are not nearly as flexible as C's.) [...] > You're trying too hard. I don't think the language needs to bother > providing solutions, it just needs to specify the limitations. So this issue (overflowing at the top end of the range) *isn't* something you dislike about C-style for loops. Good to know. > If the user needs to know about, and remember in the rare instance it > comes up, dedicated language features, then the user can also come up > with their own workarounds as I showed. Eg. in C: > > long long int i, a=INT_MIN, b=INT_MAX, n=0; > > for (i = a; i<=b; ++i) ++n; > > printf("%lld\n", n); That works only if long long int is wider than int, something the language does not guarantee. If hitting the top end of the range is a concern, I think a better workaround is to do a test and break at the bottom of the loop. That has the advantage of working even if no wider type is available. C-style for loops aren't *quite* flexible enough to express that directly, at least not cleanly. -- Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com void Void(void) { Void(); } /* The recursive call of the void */