Deutsch   English   Français   Italiano  
<vgibf8$2l858$1@dont-email.me>

View for Bookmarking (what is this?)
Look up another Usenet article

Path: ...!eternal-september.org!feeder2.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: Bart <bc@freeuk.com>
Newsgroups: comp.lang.c
Subject: Re: else ladders practice
Date: Thu, 7 Nov 2024 12:23:04 +0000
Organization: A noiseless patient Spider
Lines: 122
Message-ID: <vgibf8$2l858$1@dont-email.me>
References: <3deb64c5b0ee344acd9fbaea1002baf7302c1e8f@i2pn2.org>
 <vg2g37$37mh3$1@dont-email.me> <6724CFD2.4030607@grunge.pl>
 <vg2llt$38ons$1@dont-email.me>
 <2491a699388b5891a49ef960e1ad8bb689fdc2ed@i2pn2.org>
 <b681ee05856e165c26a5c29bf42a8d9d53843d6d@i2pn2.org>
 <vg2ttn$3a4lk$1@dont-email.me> <vg33gs$3b8n5$1@dont-email.me>
 <vg358c$3bk7t$1@dont-email.me> <vg37nr$3bo0c$1@dont-email.me>
 <vg3b98$3cc8q$1@dont-email.me> <vg5351$3pada$1@dont-email.me>
 <vg62vg$3uv02$1@dont-email.me> <vgd3ro$2pvl4$1@paganini.bofh.team>
 <vgd6jh$1hmjc$1@dont-email.me> <vge7bt$1o57r$1@dont-email.me>
 <vgfvne$25kug$1@dont-email.me>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 8bit
Injection-Date: Thu, 07 Nov 2024 13:23:04 +0100 (CET)
Injection-Info: dont-email.me; posting-host="ec686777c96cc376bc9818100d47f072";
	logging-data="2793640"; mail-complaints-to="abuse@eternal-september.org";	posting-account="U2FsdGVkX18lwmXbUJ4Ej4bXQCoToPf6"
User-Agent: Mozilla Thunderbird
Cancel-Lock: sha1:BoWE0mEMmtX5aF2tJirvDpXxqVg=
Content-Language: en-GB
In-Reply-To: <vgfvne$25kug$1@dont-email.me>
Bytes: 6325

On 06/11/2024 14:50, David Brown wrote:
> On 05/11/2024 23:48, Bart wrote:
>> On 05/11/2024 13:29, David Brown wrote:

>>> int small_int_sqrt(int x) {
>>>      if (x == 0) return 0;
>>>      if (x < 4) return 1;
>>>      if (x < 9) return 2;
>>>      if (x < 16) return 3;
>>>      unreachable();
>>> }

> "unreachable()" is a C23 standardisation of a feature found in most 
> high-end compilers.  For gcc and clang, there is 
> __builtin_unreachable(), and MSVC has its version.

So it's a kludge. Cool, I can create one of those too:

  func smallsqrt(int x)int =
      if
      elsif x=0 then  0
      elsif x<4 then  1
      elsif x<9 then  2
      elsif x<16 then 3
      dummyelse       int.min
      fi
  end

'dummyelse' is a special version of 'else' that tells the compiler that 
control will (should) never arrive there. ATM it does nothing but inform 
the reader of that and to remind the author. But later stages of the 
compiler can choose not to generate code for it, or to generate 
error-reporting code.

(A couple of things about this: the first 'if' condition and branch can 
be omitted; it starts at elsif. This removes the special-casing for the 
first of an if-elsif-chain, so to allow easier maintenance, and better 
alignment.

Second is that, unlike your C, the whole if-fi construct is a single 
expression term that yields the function return value. Hence the need 
for all branches to be present and balanced regarding their common type.

This could have been handled internally (compiler adds 'dummyelse <empty 
value for type>'), but I think it's better that it is explicit (user 
might forget to add that branch).

That int.main is something I sometimes use for in-band signalling. Here 
that is the value -9223372036854775808 so it's quite a wide band! 
Actually it is out-of-band it the user expects only result with an i32 
range.

BTW your example lets through negative values; I haven't fixed that.)

>> Getting that right will satisfy both the language (if it cared more 
>> about such matters than C apparently does), and the casual reader 
>> curious about how the function contract is met (that is, supplying 
>> that promised return int type if or when it returns).
> 
> C gets it right here.  There is no need for a return type when there is 
> no return

There is no return for only half the function! A function with a return 
type is a function that CAN return. If it can't ever return, then make 
it a procedure.

Take this function where N can never be zero; is this the right way to 
write it in C:

    int F(int N) {
        if (N==0) unreachable();
        return abc/N;              // abc is a global with value 100
    }

If doesn't look right. If I compile it with gcc (using 
__builtin_unreachable), and call F(0), then it crashes. So it doesn't do 
much does it?!

> indeed, trying to force some sort of type or "default" value 
> would be counterproductive.  It would be confusing to the reader, > add
> untestable and unexecutable source code,

But it IS confusing, since it quite clearly IS reachable. There's a 
difference between covering all possible values of N, so that is 
genuinely is unreachable, and having code that COULD be reachable.

> Let's now look at another alternative - have the function check for 
> validity, and return some kind of error signal if the input is invalid. 
> There are two ways to do this - we can have a value of the main return 
> type acting as an error signal, or we can have an additional return value.
....
> All in all, we have a significant costs in various aspects, with no real 
> benefit, all in the name of a mistaken belief that we are avoiding 
> undefined behaviour. 

This is all a large and complex subject. But it's not really the point 
of the discussion.

I'm not talking about what happens when running a program, but what 
happens at compilation, and satisfying the needs of the language.

C here is less strict in being happy to have parts of a function body as 
no-go areas where various requirements can be ignored, like a function 
with a designed return type T, being allowed to return without 
satisfying that need.

Here, you demostrated bolted-on hacks that are not part of the language, 
like the snappy __builtin_unreachable (the () are apparently optional). 
I can't see however that it does much.

It is a fact C as a language allows this:

   T F() {}           // T is not void

(I've had to qualify T - point number 9 in procedures vs. function.)

All that C says is that control flow running into that closing }, 
without encountering a 'return x', is UB.

IMV, sloppy. My language simply doesn't allow it.