Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #387379 > unrolled thread

how cast works?

Started byThiago Adams <thiago.adams@gmail.com>
First post2024-08-07 08:28 -0300
Last post2024-08-07 23:03 +0000
Articles 20 on this page of 121 — 14 participants

Back to article view | Back to comp.lang.c


Contents

  how cast works? Thiago Adams <thiago.adams@gmail.com> - 2024-08-07 08:28 -0300
    Re: how cast works? Thiago Adams <thiago.adams@gmail.com> - 2024-08-07 08:33 -0300
      Re: how cast works? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2024-08-07 13:13 -0700
      Re: how cast works? Tim Rentsch <tr.17687@z991.linuxsc.com> - 2024-08-11 17:43 -0700
        Re: how cast works? Vir Campestris <vir.campestris@invalid.invalid> - 2024-08-12 11:51 +0100
          Challenge/exercise problem - signum() function Tim Rentsch <tr.17687@z991.linuxsc.com> - 2024-08-12 08:17 -0700
            Re: Challenge/exercise problem - signum() function Lew Pitcher <lew.pitcher@digitalfreehold.ca> - 2024-08-12 16:07 +0000
              Re: Challenge/exercise problem - signum() function Tim Rentsch <tr.17687@z991.linuxsc.com> - 2024-08-12 09:57 -0700
    Re: how cast works? Dan Purgert <dan@djph.net> - 2024-08-07 20:00 +0000
      Re: how cast works? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2024-08-07 13:26 -0700
      Re: how cast works? Lawrence D'Oliveiro <ldo@nz.invalid> - 2024-08-07 23:00 +0000
      Re: how cast works? Thiago Adams <thiago.adams@gmail.com> - 2024-08-08 08:14 -0300
        Re: how cast works? Bart <bc@freeuk.com> - 2024-08-08 14:23 +0100
          Re: how cast works? Michael S <already5chosen@yahoo.com> - 2024-08-08 19:32 +0300
            Re: how cast works? Thiago Adams <thiago.adams@gmail.com> - 2024-08-08 14:11 -0300
            Re: how cast works? Bart <bc@freeuk.com> - 2024-08-08 18:29 +0100
              Re: how cast works? Thiago Adams <thiago.adams@gmail.com> - 2024-08-08 14:50 -0300
                Re: how cast works? Thiago Adams <thiago.adams@gmail.com> - 2024-08-08 14:57 -0300
                Re: how cast works? Bart <bc@freeuk.com> - 2024-08-08 19:01 +0100
                  Re: how cast works? Thiago Adams <thiago.adams@gmail.com> - 2024-08-08 15:13 -0300
                Re: how cast works? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2024-08-08 12:29 -0700
              Re: how cast works? David Brown <david.brown@hesbynett.no> - 2024-08-08 19:58 +0200
                Re: how cast works? Bart <bc@freeuk.com> - 2024-08-08 20:09 +0100
                  Re: how cast works? David Brown <david.brown@hesbynett.no> - 2024-08-09 00:32 +0200
                    Re: how cast works? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2024-08-08 16:14 -0700
                      Re: how cast works? Lawrence D'Oliveiro <ldo@nz.invalid> - 2024-08-09 02:47 +0000
                        Re: how cast works? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2024-08-08 22:55 -0700
                        Re: how cast works? James Kuyper <jameskuyper@alumni.caltech.edu> - 2024-08-09 02:08 -0400
                      Re: how cast works? David Brown <david.brown@hesbynett.no> - 2024-08-09 18:16 +0200
                        Re: how cast works? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2024-08-09 12:18 -0700
                          Re: how cast works? Tim Rentsch <tr.17687@z991.linuxsc.com> - 2024-08-11 17:07 -0700
                            Re: how cast works? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2024-08-11 20:14 -0700
                              Re: how cast works? Tim Rentsch <tr.17687@z991.linuxsc.com> - 2024-09-03 06:02 -0700
                    Re: how cast works? Bart <bc@freeuk.com> - 2024-08-09 01:56 +0100
                      Re: how cast works? David Brown <david.brown@hesbynett.no> - 2024-08-09 19:08 +0200
                        Re: how cast works? Bart <bc@freeuk.com> - 2024-08-10 11:03 +0100
                  Re: how cast works? Lawrence D'Oliveiro <ldo@nz.invalid> - 2024-08-09 02:45 +0000
        Re: how cast works? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2024-08-08 12:42 -0700
          Re: how cast works? Thiago Adams <thiago.adams@gmail.com> - 2024-08-08 17:34 -0300
            Re: how cast works? Bart <bc@freeuk.com> - 2024-08-08 22:41 +0100
              Re: how cast works? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2024-08-08 16:17 -0700
                Re: how cast works? Bart <bc@freeuk.com> - 2024-08-09 11:04 +0100
                  Re: how cast works? David Brown <david.brown@hesbynett.no> - 2024-08-09 19:12 +0200
                    Re: how cast works? Bart <bc@freeuk.com> - 2024-08-12 15:36 +0100
                  Re: how cast works? James Kuyper <jameskuyper@alumni.caltech.edu> - 2024-08-09 13:57 -0400
                    Re: how cast works? Bart <bc@freeuk.com> - 2024-08-09 21:59 +0100
                      Re: how cast works? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2024-08-09 14:47 -0700
                        Re: how cast works? Bart <bc@freeuk.com> - 2024-08-10 00:32 +0100
                          Re: how cast works? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2024-08-09 17:12 -0700
                      Re: how cast works? James Kuyper <jameskuyper@alumni.caltech.edu> - 2024-08-09 18:29 -0400
                        Re: how cast works? David Brown <david.brown@hesbynett.no> - 2024-08-13 11:18 +0200
                        Re: how cast works? Bart <bc@freeuk.com> - 2024-08-13 11:34 +0100
                        Re: how cast works? James Kuyper <jameskuyper@alumni.caltech.edu> - 2024-08-13 07:51 -0400
                          Re: how cast works? Bart <bc@freeuk.com> - 2024-08-13 14:01 +0100
                            Re: how cast works? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2024-08-13 12:46 -0700
                              Re: how cast works? Bart <bc@freeuk.com> - 2024-08-13 21:51 +0100
                                Re: how cast works? Tim Rentsch <tr.17687@z991.linuxsc.com> - 2024-08-13 16:46 -0700
                                  Re: how cast works? Bart <bc@freeuk.com> - 2024-08-14 00:56 +0100
                                    Re: how cast works? Tim Rentsch <tr.17687@z991.linuxsc.com> - 2024-08-18 03:37 -0700
                    Re: how cast works? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2024-08-09 14:29 -0700
                      Re: how cast works? James Kuyper <jameskuyper@alumni.caltech.edu> - 2024-08-09 18:35 -0400
                    Re: how cast works? Kaz Kylheku <643-408-1753@kylheku.com> - 2024-08-09 21:30 +0000
                      Re: how cast works? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2024-08-09 14:57 -0700
                        Re: how cast works? Kaz Kylheku <643-408-1753@kylheku.com> - 2024-08-09 23:14 +0000
                          Re: how cast works? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2024-08-09 16:58 -0700
                            Re: how cast works? Kaz Kylheku <643-408-1753@kylheku.com> - 2024-08-10 00:06 +0000
                              Re: how cast works? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2024-08-09 17:27 -0700
                              Re: how cast works? James Kuyper <jameskuyper@alumni.caltech.edu> - 2024-08-09 20:31 -0400
                            Re: how cast works? Bart <bc@freeuk.com> - 2024-08-10 01:11 +0100
                              Re: how cast works? David Brown <david.brown@hesbynett.no> - 2024-08-13 11:23 +0200
                          Re: how cast works? Tim Rentsch <tr.17687@z991.linuxsc.com> - 2024-08-11 17:32 -0700
                      Re: how cast works? James Kuyper <jameskuyper@alumni.caltech.edu> - 2024-08-09 18:35 -0400
                      Re: how cast works? Tim Rentsch <tr.17687@z991.linuxsc.com> - 2024-08-11 17:27 -0700
                  Re: how cast works? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2024-08-09 12:23 -0700
                    Re: how cast works? Bart <bc@freeuk.com> - 2024-08-09 21:31 +0100
                      Re: how cast works? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2024-08-09 13:49 -0700
                        Re: how cast works? Bart <bc@freeuk.com> - 2024-08-09 22:01 +0100
                  Re: how cast works? Tim Rentsch <tr.17687@z991.linuxsc.com> - 2024-08-12 00:33 -0700
                    Re: how cast works? Bart <bc@freeuk.com> - 2024-08-12 12:21 +0100
                Re: how cast works? Tim Rentsch <tr.17687@z991.linuxsc.com> - 2024-08-11 17:46 -0700
                  Re: how cast works? Bart <bc@freeuk.com> - 2024-08-12 02:00 +0100
                    Re: how cast works? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2024-08-11 20:23 -0700
                    Re: how cast works? Tim Rentsch <tr.17687@z991.linuxsc.com> - 2024-08-11 20:37 -0700
                      Re: how cast works? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2024-08-11 21:33 -0700
                        Re: how cast works? Ben Bacarisse <ben@bsb.me.uk> - 2024-08-12 16:57 +0100
                          Re: how cast works? Tim Rentsch <tr.17687@z991.linuxsc.com> - 2024-08-12 10:04 -0700
                            Re: how cast works? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2024-08-12 13:35 -0700
              Re: how cast works? Thiago Adams <thiago.adams@gmail.com> - 2024-08-09 07:57 -0300
                Re: how cast works? Bart <bc@freeuk.com> - 2024-08-09 16:25 +0100
                  Re: how cast works? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2024-08-09 12:06 -0700
                Re: how cast works? David Brown <david.brown@hesbynett.no> - 2024-08-09 19:20 +0200
                  Re: how cast works? Thiago Adams <thiago.adams@gmail.com> - 2024-08-09 15:54 -0300
                    Re: how cast works? Thiago Adams <thiago.adams@gmail.com> - 2024-08-09 16:05 -0300
                      Re: how cast works? David Brown <david.brown@hesbynett.no> - 2024-08-09 21:43 +0200
                      Re: how cast works? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2024-08-09 13:28 -0700
                    Re: how cast works? David Brown <david.brown@hesbynett.no> - 2024-08-09 22:01 +0200
                      Re: how cast works? Bart <bc@freeuk.com> - 2024-08-10 11:17 +0100
                        Re: how cast works? Thiago Adams <thiago.adams@gmail.com> - 2024-08-10 10:15 -0300
                          Re: how cast works? Bart <bc@freeuk.com> - 2024-08-10 17:14 +0100
                            Re: how cast works? Thiago Adams <thiago.adams@gmail.com> - 2024-08-10 20:01 -0300
                              Re: how cast works? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2024-08-10 17:10 -0700
                                Re: how cast works? Thiago Adams <thiago.adams@gmail.com> - 2024-08-11 09:23 -0300
                                  Re: how cast works? Bart <bc@freeuk.com> - 2024-08-11 13:30 +0100
                                    Re: how cast works? Thiago Adams <thiago.adams@gmail.com> - 2024-08-11 14:16 -0300
                                  Re: how cast works? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2024-08-11 13:38 -0700
                                    Re: how cast works? Bart <bc@freeuk.com> - 2024-08-12 12:24 +0100
                    Re: how cast works? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2024-08-09 13:26 -0700
                      Re: how cast works? Thiago Adams <thiago.adams@gmail.com> - 2024-08-09 18:01 -0300
                        Re: how cast works? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2024-08-09 14:53 -0700
                Re: how cast works? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2024-08-09 12:03 -0700
                  Re: how cast works? Thiago Adams <thiago.adams@gmail.com> - 2024-08-09 16:22 -0300
            Re: how cast works? David Brown <david.brown@hesbynett.no> - 2024-08-09 00:36 +0200
      Re: how cast works? Dan Purgert <dan@djph.net> - 2024-08-08 14:08 +0000
      Re: how cast works? Lawrence D'Oliveiro <ldo@nz.invalid> - 2024-08-09 02:42 +0000
    Re: how cast works? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2024-08-07 13:08 -0700
      Re: how cast works? Thiago Adams <thiago.adams@gmail.com> - 2024-08-08 08:35 -0300
        Re: how cast works? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2024-08-08 12:39 -0700
        Re: how cast works? James Kuyper <jameskuyper@alumni.caltech.edu> - 2024-08-08 18:40 -0400
          Re: how cast works? Tim Rentsch <tr.17687@z991.linuxsc.com> - 2024-08-11 17:15 -0700
      Is there an audio book version (Was: how cast works?) gazelle@shell.xmission.com (Kenny McCormack) - 2024-08-08 16:19 +0000
    Re: how cast works? Lawrence D'Oliveiro <ldo@nz.invalid> - 2024-08-07 23:03 +0000

Page 2 of 7 — ← Prev page 1 [2] 3 4 5 6 7  Next page →


#387406

FromKeith Thompson <Keith.S.Thompson+u@gmail.com>
Date2024-08-08 12:29 -0700
Message-ID<8734neak5d.fsf@nosuchdomain.example.com>
In reply to#387400
Thiago Adams <thiago.adams@gmail.com> writes:
[...]
> For constexpr the compiler does not accept initialization invalid types.
> for instance.
>
>  constexpr char s = 12345;
>
> <source>:6:21: error: constexpr initializer evaluates to 12345 which
> is not exactly representable in type 'const char'
>     6 |  constexpr char s = 12345;

The problem there is the value, not the type.  This:

    constexpr char s = 10;

is perfectly valid.  The initializer is of type int, not char, but it's
implicitly converted.

[...]

-- 
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
void Void(void) { Void(); } /* The recursive call of the void */

[toc] | [prev] | [next] | [standalone]


#387402

FromDavid Brown <david.brown@hesbynett.no>
Date2024-08-08 19:58 +0200
Message-ID<v9310a$4v1a$2@dont-email.me>
In reply to#387398
On 08/08/2024 19:29, Bart wrote:
> On 08/08/2024 17:32, Michael S wrote:
>  > On Thu, 8 Aug 2024 14:23:44 +0100
>  > Bart <bc@freeuk.com> wrote:
>  >> Try godbolt.org. Type in a fragment of code that does different kinds
>  >> of casts (it needs to be well-formed, so inside a function), and see
>  >> what code is produced with different C compilers.
>  >>
>  >> Use -O0 so that the code isn't optimised out of existence, and so
>  >> that you can more easily match it to the C ource.
>  >>
>  >>
>  >
>  >
>  > I'd recommend an opposite - use -O2 so the cast that does nothing
>  > optimized away.
>  >
>  > int foo_i2i(int x) { return (int)x; }
>  > int foo_u2i(unsigned x) { return (int)x; }
>  > int foo_b2i(_Bool x) { return (int)x; }
>  > int foo_d2i(double x) { return (int)x; }
> The OP is curious as to what's involved when a conversion is done. 
> Hiding or eliminating code isn't helpful in that case; the results can 
> also be misleading:

Michael is correct - the OP should enable optimisation, precisely to 
avoid the issue you are concerned about.  Without optimisation, the 
results are misleading - they will only show things that are /not/ 
involved in the conversion, swamping the useful results with code that 
messes about putting data on and off the stack.  When optimised 
compilation shows that no code is generated, it is a very clear 
indication that no operations are needed for the conversions in question 
- unoptimized code hides that.

> 
> Take this example:
> 
>    void fred(void) {
>     _Bool b;
>       int i;
>       i=b;
>    }
> 
> Unoptimised, it generates this code:
> 
>          push    rbp
>          mov     rbp, rsp
> 
>          mov     al, byte ptr [rbp - 1]
>          and     al, 1
>          movzx   eax, al
>          mov     dword ptr [rbp - 8], eax
> 
>          pop     rbp
>          ret
> 
> You can see from this that a Bool occupies one byte; it is masked to 0/1 
> (so it doesn't trust it to contain only 0/1), then it is widened to an 
> int size.
> 

No, you can't see that.  All you can see is garbage in, garbage out. 
You have to start with a function that has some meaning!

> With optimisation turned on, even at -O1, it produces this:
> 
>          ret

Try again with:

	int foo(bool x) { return x; }

	bool bar(int x) { return x; }

Try it with -O0 and -O1, and then tell us which you think gives a 
clearer indication of the operations needed.

[toc] | [prev] | [next] | [standalone]


#387405

FromBart <bc@freeuk.com>
Date2024-08-08 20:09 +0100
Message-ID<v93565$6ffo$1@dont-email.me>
In reply to#387402
On 08/08/2024 18:58, David Brown wrote:
> On 08/08/2024 19:29, Bart wrote:
>> On 08/08/2024 17:32, Michael S wrote:
>>  > On Thu, 8 Aug 2024 14:23:44 +0100
>>  > Bart <bc@freeuk.com> wrote:
>>  >> Try godbolt.org. Type in a fragment of code that does different kinds
>>  >> of casts (it needs to be well-formed, so inside a function), and see
>>  >> what code is produced with different C compilers.
>>  >>
>>  >> Use -O0 so that the code isn't optimised out of existence, and so
>>  >> that you can more easily match it to the C ource.
>>  >>
>>  >>
>>  >
>>  >
>>  > I'd recommend an opposite - use -O2 so the cast that does nothing
>>  > optimized away.
>>  >
>>  > int foo_i2i(int x) { return (int)x; }
>>  > int foo_u2i(unsigned x) { return (int)x; }
>>  > int foo_b2i(_Bool x) { return (int)x; }
>>  > int foo_d2i(double x) { return (int)x; }
>> The OP is curious as to what's involved when a conversion is done. 
>> Hiding or eliminating code isn't helpful in that case; the results can 
>> also be misleading:
> 
> Michael is correct - the OP should enable optimisation, precisely to 
> avoid the issue you are concerned about.  Without optimisation, the 
> results are misleading - they will only show things that are /not/ 
> involved in the conversion, swamping the useful results with code that 
> messes about putting data on and off the stack.  When optimised 
> compilation shows that no code is generated, it is a very clear 
> indication that no operations are needed for the conversions in question 
> - unoptimized code hides that.
> 
>>
>> Take this example:
>>
>>    void fred(void) {
>>     _Bool b;
>>       int i;
>>       i=b;
>>    }
>>
>> Unoptimised, it generates this code:
>>
>>          push    rbp
>>          mov     rbp, rsp
>>
>>          mov     al, byte ptr [rbp - 1]
>>          and     al, 1
>>          movzx   eax, al
>>          mov     dword ptr [rbp - 8], eax
>>
>>          pop     rbp
>>          ret
>>
>> You can see from this that a Bool occupies one byte; it is masked to 
>> 0/1 (so it doesn't trust it to contain only 0/1), then it is widened 
>> to an int size.
>>
> 
> No, you can't see that.  All you can see is garbage in, garbage out. You 
> have to start with a function that has some meaning!

Sorry but my function is perfectly valid. It's taking a Bool value and 
converting it to an int.

Perhaps you don't understand x86 code? I'll tell you: it loads that 
/byte-sized/ value, masks it, and widens it to an int. I'm surprised you 
can't see that.

But I suspect a long gaslighting session coming on, where you refute the 
evidence that everyone else can see!


> 
>> With optimisation turned on, even at -O1, it produces this:
>>
>>          ret
> 
> Try again with:
> 
>      int foo(bool x) { return x; }
> 
>      bool bar(int x) { return x; }
> 
> Try it with -O0 and -O1, and then tell us which you think gives a 
> clearer indication of the operations needed.

Michael is wrong and so are you.

If you want to know what casting from bool to int entails, then testing 
it via a function call like this is the wrong way to do it, since half 
of it depends on what happens when evaluating arguments at the call site.

Especially if you let the compiler do what it likes, like using its 
knowledge of that call process, which is not displayed here in the 
optimised code of the function body.


So I have some questions of you:

* How exactly is a _Bool value (which occupies one byte) translated to a 
32-bit signed integer? What is involved?

This is machine independent other than the sizes mentioned.

Given your answer, how does it correlate with either:


    mov eax,    edi     ; from your test; both optimised code

    <nothing>           ; from my test



The advantage of unoptimised code is that it will contain everything 
that is normally involved; it doesn't throw anything away.

It doesn't require convincing the compiler that you're doing something 
useful to avoid it eliminating most or all your code, or turning it 
something that is just plain misleading.

That might be useful when compiling a huge production version of an app, 
but it is useless when trying to shed light on an isolated fragment of code.

Look, just forget it, I'm not in the mood for another marathon subthread.

So, what's involved in turning Bool to int? According to your examples 
with -O1: nothing. You just copy 32 bits unchanged from one to the 
other. Mildly surprising, but you are of course right, right?

However, now *I* have a problem, figuring out why on earth C compiler 
does the conversion like this:

     movsx eax, byte [source]

Because this must be wrong, right?

[toc] | [prev] | [next] | [standalone]


#387411

FromDavid Brown <david.brown@hesbynett.no>
Date2024-08-09 00:32 +0200
Message-ID<v93h12$9vom$1@dont-email.me>
In reply to#387405
On 08/08/2024 21:09, Bart wrote:
> On 08/08/2024 18:58, David Brown wrote:
>> On 08/08/2024 19:29, Bart wrote:
>>> On 08/08/2024 17:32, Michael S wrote:
>>>  > On Thu, 8 Aug 2024 14:23:44 +0100
>>>  > Bart <bc@freeuk.com> wrote:
>>>  >> Try godbolt.org. Type in a fragment of code that does different 
>>> kinds
>>>  >> of casts (it needs to be well-formed, so inside a function), and see
>>>  >> what code is produced with different C compilers.
>>>  >>
>>>  >> Use -O0 so that the code isn't optimised out of existence, and so
>>>  >> that you can more easily match it to the C ource.
>>>  >>
>>>  >>
>>>  >
>>>  >
>>>  > I'd recommend an opposite - use -O2 so the cast that does nothing
>>>  > optimized away.
>>>  >
>>>  > int foo_i2i(int x) { return (int)x; }
>>>  > int foo_u2i(unsigned x) { return (int)x; }
>>>  > int foo_b2i(_Bool x) { return (int)x; }
>>>  > int foo_d2i(double x) { return (int)x; }
>>> The OP is curious as to what's involved when a conversion is done. 
>>> Hiding or eliminating code isn't helpful in that case; the results 
>>> can also be misleading:
>>
>> Michael is correct - the OP should enable optimisation, precisely to 
>> avoid the issue you are concerned about.  Without optimisation, the 
>> results are misleading - they will only show things that are /not/ 
>> involved in the conversion, swamping the useful results with code that 
>> messes about putting data on and off the stack.  When optimised 
>> compilation shows that no code is generated, it is a very clear 
>> indication that no operations are needed for the conversions in 
>> question - unoptimized code hides that.
>>
>>>
>>> Take this example:
>>>
>>>    void fred(void) {
>>>     _Bool b;
>>>       int i;
>>>       i=b;
>>>    }
>>>
>>> Unoptimised, it generates this code:
>>>
>>>          push    rbp
>>>          mov     rbp, rsp
>>>
>>>          mov     al, byte ptr [rbp - 1]
>>>          and     al, 1
>>>          movzx   eax, al
>>>          mov     dword ptr [rbp - 8], eax
>>>
>>>          pop     rbp
>>>          ret
>>>
>>> You can see from this that a Bool occupies one byte; it is masked to 
>>> 0/1 (so it doesn't trust it to contain only 0/1), then it is widened 
>>> to an int size.
>>>
>>
>> No, you can't see that.  All you can see is garbage in, garbage out. 
>> You have to start with a function that has some meaning!
> 
> Sorry but my function is perfectly valid. It's taking a Bool value and 
> converting it to an int.

No, it is not.

Attempting to use the value of a non-static local variable that has not 
been initialised or assigned is undefined behaviour.  Your function is 
garbage.  No one can draw any conclusions about how meaningless code is 
compiled.

> 
> Perhaps you don't understand x86 code? I'll tell you: it loads that 
> /byte-sized/ value, masks it, and widens it to an int. I'm surprised you 
> can't see that.
> 

I understand x86 well enough - perhaps not as well as you, but well 
enough.  I do, however, understand C better than you, it seems.  The x86 
code is irrelevant to the fact that your code has undefined behaviour. 
(And even if it were defined, it would still do nothing relevant.)

> But I suspect a long gaslighting session coming on, where you refute the 
> evidence that everyone else can see!
> 

You are projecting.

Look, it is extraordinarily simple to write functions that /actually/ do 
the conversions under discussion.  Why waste time writing nonsense 
functions that do that?

> 
>>
>>> With optimisation turned on, even at -O1, it produces this:
>>>
>>>          ret
>>
>> Try again with:
>>
>>      int foo(bool x) { return x; }
>>
>>      bool bar(int x) { return x; }
>>
>> Try it with -O0 and -O1, and then tell us which you think gives a 
>> clearer indication of the operations needed.
> 
> Michael is wrong and so are you.
> 
> If you want to know what casting from bool to int entails, then testing 
> it via a function call like this is the wrong way to do it, since half kj
> of it depends on what happens when evaluating arguments at the call site.
> 

Nope.

But if you prefer, just use external variables:

int i;
bool b;

void to_int_0(void) { i = b; }
void to_bool_0(void) { b = i; }

<https://www.godbolt.org/z/eT9Y84Gx4>


Again, look at the two functions with -O0 and -O1, and tell me which is 
clearer.

> Especially if you let the compiler do what it likes, like using its 
> knowledge of that call process, which is not displayed here in the 
> optimised code of the function body.
> 
> 
> So I have some questions of you:
> 
> * How exactly is a _Bool value (which occupies one byte) translated to a 
> 32-bit signed integer? What is involved?
> 

A _Bool is always either 0 or 1.  The conversion is whatever the 
compiler needs to give an int of value 0 or 1.

The implementation details depend entirely on the target.  Typically, if 
the _Bool is in memory, then a single byte is read and zero-extended to 
the width of a register.  If the _Bool is passed to a function as a 
parameter, it is usually already extended - but that will depend on the 
calling conventions.

> This is machine independent other than the sizes mentioned.
>

The specification is independent - it is given by the C standards.  The 
implementation is most certainly not machine independent.  It is also 
not necessarily consistent - compilers can and do pick different code 
depending on the circumstances (where the _Bool came from, and how the 
int is going to be used).  You are even wrong in stating that a _Bool 
occupies one byte, since that is not a requirement for a C 
implementation (though I don't know of any real-world C implementations 
with larger _Bool's).


> Given your answer, how does it correlate with either:
> 
> 
>     mov eax,    edi     ; from your test; both optimised code
> 

Looks fine.

>     <nothing>           ; from my test
> 

That's fine for the nonsense function you wrote.

> 
> 
> The advantage of unoptimised code is that it will contain everything 
> that is normally involved; it doesn't throw anything away.
> 

No, it does not - because normal code generated by C compilers used by C 
programmers who want sensible results will be the result of compiling 
with optimisation, and will look very different.

> It doesn't require convincing the compiler that you're doing something 
> useful to avoid it eliminating most or all your code, or turning it 
> something that is just plain misleading.
> 

You have /never/ understood how to look at generated code, have you?

> That might be useful when compiling a huge production version of an app, 
> but it is useless when trying to shed light on an isolated fragment of 
> code.
> 
> Look, just forget it, I'm not in the mood for another marathon subthread.
> 

OK.  I expect the OP to understand these things better.

> So, what's involved in turning Bool to int? According to your examples 
> with -O1: nothing. You just copy 32 bits unchanged from one to the 
> other. Mildly surprising, but you are of course right, right?
> 

Yes, I am right - and I don't see that as even mildly surprising here. 
That's how you convert a _Bool in a register to an int in a register. 
You'll see equally little code when converting between signed and 
unsigned types, or various other integer types.

> However, now *I* have a problem, figuring out why on earth C compiler 
> does the conversion like this:
> 
>      movsx eax, byte [source]
> 
> Because this must be wrong, right?
> 
> 

No.  You are asking it to do something else - you are asking it to load 
a _Bool from memory, not just convert it.

[toc] | [prev] | [next] | [standalone]


#387414

FromKeith Thompson <Keith.S.Thompson+u@gmail.com>
Date2024-08-08 16:14 -0700
Message-ID<87frre8v5q.fsf@nosuchdomain.example.com>
In reply to#387411
David Brown <david.brown@hesbynett.no> writes:
[...]
> A _Bool is always either 0 or 1.  The conversion is whatever the
> compiler needs to give an int of value 0 or 1.

The value of a _Bool object is always either 0 or 1 *unless* the program
does something weird.

C23 is a bit clearer about the representation of bool (still also called
_Bool) than previous editions.  It states (draft N3220) that :

    The type bool shall have one value bit and (sizeof(bool)*CHAR_BIT)-1
    padding bits.

There are several ways to force a representation other than 00000000 or
00000001 into a _Bool object, including a union, memset(), or type
punning via a pointer cast.

C23 dropped the term "trap representation", replacing it with "non-value
representation" -- a reasonable change, since accessing a trap
representation is not guaranteed to cause the program to "perform a
trap" (defined as "interrupt execution of the program such that no
further operations are performed").

It doesn't specify whether setting the padding bits to 1 results in a
non-value representation.

If non-zero padding bits create a non-value representation, then
accessing a bool object holding such a representation has undefined
behavior.  It could, among other things, yield the same value implied by
the representation as if it were an ordinary integer of the same size.

If there are no non-value representations, then only the
single value bit determines the value, which is either false or true.

As you mentioned, I expect that sizeof (bool) will normally be 1, but an
implementation could make it wider, e.g. with 1 value bit and 31 padding
bits.

[...]

-- 
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
void Void(void) { Void(); } /* The recursive call of the void */

[toc] | [prev] | [next] | [standalone]


#387419

FromLawrence D'Oliveiro <ldo@nz.invalid>
Date2024-08-09 02:47 +0000
Message-ID<v93vvc$hjg3$4@dont-email.me>
In reply to#387414
On Thu, 08 Aug 2024 16:14:09 -0700, Keith Thompson wrote:

> The value of a _Bool object is always either 0 or 1 *unless* the program
> does something weird.

If a variable is declared to be of a particular type, does that mean that 
any possible value of that variable is, by definition, interpreted as some 
instance of that type?

[toc] | [prev] | [next] | [standalone]


#387420

FromKeith Thompson <Keith.S.Thompson+u@gmail.com>
Date2024-08-08 22:55 -0700
Message-ID<877ccq8ck7.fsf@nosuchdomain.example.com>
In reply to#387419
Lawrence D'Oliveiro <ldo@nz.invalid> writes:
> On Thu, 08 Aug 2024 16:14:09 -0700, Keith Thompson wrote:
>> The value of a _Bool object is always either 0 or 1 *unless* the program
>> does something weird.
>
> If a variable is declared to be of a particular type, does that mean that 
> any possible value of that variable is, by definition, interpreted as some 
> instance of that type?

Of course, given what "value" means.  How could that not be the case?

If you mean any possible *representation* (for example, if _Bool is 8
bits there are 256 possible representations), I refer you to my previous
discussion of non-value representations (formerly called trap
representations) in the text that you snipped.

-- 
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
void Void(void) { Void(); } /* The recursive call of the void */

[toc] | [prev] | [next] | [standalone]


#387421

FromJames Kuyper <jameskuyper@alumni.caltech.edu>
Date2024-08-09 02:08 -0400
Message-ID<v94bo4$jmsp$1@dont-email.me>
In reply to#387419
On 8/8/24 22:47, Lawrence D'Oliveiro wrote:
> On Thu, 08 Aug 2024 16:14:09 -0700, Keith Thompson wrote:
> 
>> The value of a _Bool object is always either 0 or 1 *unless* the program
>> does something weird.
> 
> If a variable is declared to be of a particular type, does that mean that 
> any possible value of that variable is, by definition, interpreted as some 
> instance of that type?

No, modulo some uncertainties about what precisely you mean by "possible
value". I'm assuming that you mean object representations that can be
created by your code.

Every object type has a range of representable values. For each of those
representable values there's one or more object representations that
represent that value.  Writing a representable value to an object using
code with defined behavior and an lvalue of a given type always results
in a valid object representation according to that type.

However, there can be, and often are, object representations that do not
represent a value when interpreted according to the type of the lvalue
used to read them. These are called non-value representations. This can
only happen as a result of type-punning or code that has undefined behavior.

Here's what the standard says about such situations:
"If such a representation is read by an lvalue expression that does not
have character type, the behavior is undefined. If such a representation
is produced by a side effect that modifies all or any part of the object
by an lvalue expression that does not have character type, the behavior
is undefined.55)" (6.2.6.1p5)

So, no, not all object representations represent valid values of the
type used to access them, and it's a very bad thing when you let that
happen.

[toc] | [prev] | [next] | [standalone]


#387425

FromDavid Brown <david.brown@hesbynett.no>
Date2024-08-09 18:16 +0200
Message-ID<v95fcj$pv2g$1@dont-email.me>
In reply to#387414
On 09/08/2024 01:14, Keith Thompson wrote:
> David Brown <david.brown@hesbynett.no> writes:
> [...]
>> A _Bool is always either 0 or 1.  The conversion is whatever the
>> compiler needs to give an int of value 0 or 1.
> 
> The value of a _Bool object is always either 0 or 1 *unless* the program
> does something weird.

True.  But attempting to use a _Bool object (as a _Bool) that does not 
contain either 0 or 1 is going to be undefined behaviour (at least it 
was on the platform where I saw this happen as a code bug).

> 
> C23 is a bit clearer about the representation of bool (still also called
> _Bool) than previous editions.  It states (draft N3220) that :
> 
>      The type bool shall have one value bit and (sizeof(bool)*CHAR_BIT)-1
>      padding bits.
> 
> There are several ways to force a representation other than 00000000 or
> 00000001 into a _Bool object, including a union, memset(), or type
> punning via a pointer cast.
> 
> C23 dropped the term "trap representation", replacing it with "non-value
> representation" -- a reasonable change, since accessing a trap
> representation is not guaranteed to cause the program to "perform a
> trap" (defined as "interrupt execution of the program such that no
> further operations are performed").
> 
> It doesn't specify whether setting the padding bits to 1 results in a
> non-value representation.

That's probably an implementation-defined issue, is it not?

> 
> If non-zero padding bits create a non-value representation, then
> accessing a bool object holding such a representation has undefined
> behavior.  It could, among other things, yield the same value implied by
> the representation as if it were an ordinary integer of the same size.
> 
> If there are no non-value representations, then only the
> single value bit determines the value, which is either false or true.
> 
> As you mentioned, I expect that sizeof (bool) will normally be 1, but an
> implementation could make it wider, e.g. with 1 value bit and 31 padding
> bits.
> 


[toc] | [prev] | [next] | [standalone]


#387438

FromKeith Thompson <Keith.S.Thompson+u@gmail.com>
Date2024-08-09 12:18 -0700
Message-ID<87ttft7bei.fsf@nosuchdomain.example.com>
In reply to#387425
David Brown <david.brown@hesbynett.no> writes:
> On 09/08/2024 01:14, Keith Thompson wrote:
>> David Brown <david.brown@hesbynett.no> writes:
>> [...]
>>> A _Bool is always either 0 or 1.  The conversion is whatever the
>>> compiler needs to give an int of value 0 or 1.
>> 
>> The value of a _Bool object is always either 0 or 1 *unless* the
>> program does something weird.
>
> True.  But attempting to use a _Bool object (as a _Bool) that does not
> contain either 0 or 1 is going to be undefined behaviour (at least it
> was on the platform where I saw this happen as a code bug).

It depends on whether representations with non-zero padding bits are
treated as trap representations (non-value representations in C23) or
not.

[...]

>> It doesn't specify whether setting the padding bits to 1 results in a
>> non-value representation.
>
> That's probably an implementation-defined issue, is it not?

I'm not sure whether it's implementation-defined or unspecified.
I don't see any mention of trap/non-value representations in Annex J.

[...]

-- 
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
void Void(void) { Void(); } /* The recursive call of the void */

[toc] | [prev] | [next] | [standalone]


#387488

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2024-08-11 17:07 -0700
Message-ID<86frrak3hf.fsf@linuxsc.com>
In reply to#387438
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

> David Brown <david.brown@hesbynett.no> writes:
>
>> On 09/08/2024 01:14, Keith Thompson wrote:
>>
>>> David Brown <david.brown@hesbynett.no> writes:
>>> [...]
>>>
>>>> A _Bool is always either 0 or 1.  The conversion is whatever the
>>>> compiler needs to give an int of value 0 or 1.
>>>
>>> The value of a _Bool object is always either 0 or 1 *unless* the
>>> program does something weird.
>>
>> True.  But attempting to use a _Bool object (as a _Bool) that does not
>> contain either 0 or 1 is going to be undefined behaviour (at least it
>> was on the platform where I saw this happen as a code bug).
>
> It depends on whether representations with non-zero padding bits are
> treated as trap representations (non-value representations in C23) or
> not.

In C99 and C11, iirc, the width of _Bool may be any value between
1 and CHAR_BIT.  If the width of _Bool is greater than 1, a _Bool
may have a well-defined value that is neither 0 or 1.  My guess is
most implementations define the width of _Bool as 1, but they don't
have to (again, iirc, in C99 and C11).

>>> It doesn't specify whether setting the padding bits to 1 results in a
>>> non-value representation.
>>
>> That's probably an implementation-defined issue, is it not?
>
> I'm not sure whether it's implementation-defined or unspecified.
> I don't see any mention of trap/non-value representations in Annex J.
>
> [...]

6.2.6.1 p 2;

J.3.13 p 1, third subpoint.

[toc] | [prev] | [next] | [standalone]


#387495

FromKeith Thompson <Keith.S.Thompson+u@gmail.com>
Date2024-08-11 20:14 -0700
Message-ID<87plqee8li.fsf@nosuchdomain.example.com>
In reply to#387488
Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
> Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
>
>> David Brown <david.brown@hesbynett.no> writes:
>>
>>> On 09/08/2024 01:14, Keith Thompson wrote:
>>>
>>>> David Brown <david.brown@hesbynett.no> writes:
>>>> [...]
>>>>
>>>>> A _Bool is always either 0 or 1.  The conversion is whatever the
>>>>> compiler needs to give an int of value 0 or 1.
>>>>
>>>> The value of a _Bool object is always either 0 or 1 *unless* the
>>>> program does something weird.
>>>
>>> True.  But attempting to use a _Bool object (as a _Bool) that does not
>>> contain either 0 or 1 is going to be undefined behaviour (at least it
>>> was on the platform where I saw this happen as a code bug).
>>
>> It depends on whether representations with non-zero padding bits are
>> treated as trap representations (non-value representations in C23) or
>> not.
>
> In C99 and C11, iirc, the width of _Bool may be any value between
> 1 and CHAR_BIT.  If the width of _Bool is greater than 1, a _Bool
> may have a well-defined value that is neither 0 or 1.  My guess is
> most implementations define the width of _Bool as 1, but they don't
> have to (again, iirc, in C99 and C11).

C11 (N1570) isn't 100% clear, but I think you're right.  The conversion
rank of _Bool is less than the rank of the char types.  I don't see an
explicit statement that this implies that _Bool has less precision than
unsigned char, so conceivably a conforming implementation could give
_Bool a precision of 2*CHAR_BIT, but C23 has cleared this up so I'm not
going to worry about it (and it's possible I've missed something).

>>>> It doesn't specify whether setting the padding bits to 1 results in a
>>>> non-value representation.
>>>
>>> That's probably an implementation-defined issue, is it not?
>>
>> I'm not sure whether it's implementation-defined or unspecified.
>> I don't see any mention of trap/non-value representations in Annex J.
>>
>> [...]
>
> 6.2.6.1 p 2;

So it's implementation-defined.

N1570 :

    Except for bit-fields, objects are composed of contiguous sequences of
    one or more bytes, the number, order, and encoding of which are either
    explicitly specified or implementation-defined.

> J.3.13 p 1, third subpoint.

    The number, order, and encoding of bytes in any object (when not
    explicitly specified in this International Standard) (6.2.6.1).

(listed under Implementation-defined behavior).

Quoting the standard so that everyone else doesn't have to go look it up
(and guess which edition you're referring to).  You might consider doing
that yourself.

-- 
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
void Void(void) { Void(); } /* The recursive call of the void */

[toc] | [prev] | [next] | [standalone]


#388107

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2024-09-03 06:02 -0700
Message-ID<865xrcq49v.fsf@linuxsc.com>
In reply to#387495
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

> Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
>
>> Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
>>
>>> David Brown <david.brown@hesbynett.no> writes:
>>>
>>>> On 09/08/2024 01:14, Keith Thompson wrote:
>>>>
>>>>> David Brown <david.brown@hesbynett.no> writes:
>>>>> [...]
>>>>>
>>>>>> A _Bool is always either 0 or 1.  The conversion is whatever
>>>>>> the compiler needs to give an int of value 0 or 1.
>>>>>
>>>>> The value of a _Bool object is always either 0 or 1 *unless* the
>>>>> program does something weird.
>>>>
>>>> True.  But attempting to use a _Bool object (as a _Bool) that
>>>> does not contain either 0 or 1 is going to be undefined behaviour
>>>> (at least it was on the platform where I saw this happen as a
>>>> code bug).
>>>
>>> It depends on whether representations with non-zero padding bits
>>> are treated as trap representations (non-value representations in
>>> C23) or not.
>>
>> In C99 and C11, iirc, the width of _Bool may be any value between 1
>> and CHAR_BIT.  If the width of _Bool is greater than 1, a _Bool may
>> have a well-defined value that is neither 0 or 1.  My guess is most
>> implementations define the width of _Bool as 1, but they don't have
>> to (again, iirc, in C99 and C11).
>
> C11 (N1570) isn't 100% clear, but I think you're right.  The
> conversion rank of _Bool is less than the rank of the char types.
> I don't see an explicit statement that this implies that _Bool has
> less precision than unsigned char, [...]

C11 (and I think also C99, but I haven't checked that) states
requirements that guarantee _Bool has a width no larger than the
width of unsigned char.  I'm sure you can locate the relevant
passages.


>>>>> It doesn't specify whether setting the padding bits to 1 results
>>>>> in a non-value representation.
>>>>
>>>> That's probably an implementation-defined issue, is it not?
>>>
>>> I'm not sure whether it's implementation-defined or unspecified.
>>> I don't see any mention of trap/non-value representations in Annex
>>> J.
>>>
>>> [...]
>>
>> 6.2.6.1 p 2;
>
> So it's implementation-defined.  [...]
>
> Quoting the standard so that everyone else doesn't have to go look
> it up (and guess which edition you're referring to).  You might
> consider doing that yourself.

I choose the contents of my comments to be what I think is
appropropriate under each individual set of circumstances.
Please keep your patronizing preaching to yourself.

[toc] | [prev] | [next] | [standalone]


#387416

FromBart <bc@freeuk.com>
Date2024-08-09 01:56 +0100
Message-ID<v93pfg$c7b8$1@dont-email.me>
In reply to#387411
On 08/08/2024 23:32, David Brown wrote:
> On 08/08/2024 21:09, Bart wrote:

>> Sorry but my function is perfectly valid. It's taking a Bool value and 
>> converting it to an int.
> 
> No, it is not.
> 
> Attempting to use the value of a non-static local variable that has not 
> been initialised or assigned is undefined behaviour.  Your function is 
> garbage.  No one can draw any conclusions about how meaningless code is 
> compiled.

FFS. You really think that makes a blind bit of difference? A variable 
is not initialised, so the bool->int code shown must be just random 
rubbish generated by the compiler? You think I wouldn't spot if there 
was something amiss?

OK, let's initialise it and see what difference it actually makes. My 
code is now this:

   #include <stdbool.h>

   void BC(void) {
       _Bool b;
       int i;
       i=b;
   }

   void DB(void) {
       _Bool b=false;
       int i;
       i=b;
   }

The output from gcc -O1 is this:

BC:
         ret
DB:
         ret

There is no difference. So, even initialised, it tells me nothing about 
what might be involved in bool->int conversion. It is useless.

Now I'll try it with -O0 (line breaks added):

BC:
         push    rbp
         mov     rbp, rsp

         movzx   eax, BYTE PTR [rbp-1]
         mov     DWORD PTR [rbp-8], eax

         nop
         pop     rbp
         ret
DB:
         push    rbp
         mov     rbp, rsp
         mov     BYTE PTR [rbp-1], 0

         movzx   eax, BYTE PTR [rbp-1]
         mov     DWORD PTR [rbp-8], eax

         nop
         pop     rbp
         ret

Exactly the same code, except DB has an extra line to initialise that value.

Are you surprised it is the same? I am 99% sure that you already knew 
this, but were pretending that the code was meaningless, for reasons 
that escape me.

One more thing: the ASM code I posted earlier was from Clang 18.1, above 
it's from gcc 14.1.

The Clang code masks bit 0 of the bool value; gcc doesn't.

However, you can only know that by using -O0 in both cases. Using the 
-O1 or higher that you recommend, you only see this:

BC:
         ret

DB:
         ret

for both compilers. That is utterly useless. YMMV.


>> If you want to know what casting from bool to int entails, then 
>> testing it via a function call like this is the wrong way to do it, 
>> since half kj
>> of it depends on what happens when evaluating arguments at the call site.
>>
> 
> Nope.

So in:

      mov eax,  ecx

inside foo_b2i(), at what point did the 8-bit _Bool get turned into the 
32-bit value in ecx?

> That's fine for the nonsense function you wrote.

Actually, MS (the poster) wrote those foo_* functions .


>>
>>
>> The advantage of unoptimised code is that it will contain everything 
>> that is normally involved; it doesn't throw anything away.
>>
> 
> No, it does not - because normal code generated by C compilers used by C 
> programmers who want sensible results will be the result of compiling 
> with optimisation, and will look very different.

As I said, this isn't production code of a real program. It is a single 
line. Elsewhere you had to resort to using statics (and linkage outside 
of a function) to stop code being eliminated out of existence.


With -O0 you don't need such tricks, and don't need to think about what 
might have been removed that you really need to see.

>> So, what's involved in turning Bool to int? According to your examples 
>> with -O1: nothing. You just copy 32 bits unchanged from one to the 
>> other. Mildly surprising, but you are of course right, right?
>>
> 
> Yes, I am right - and I don't see that as even mildly surprising here. 
> That's how you convert a _Bool in a register to an int in a register. 

We don't know where the bool passed to foo_b2i came from; maybe it was 
an element of an array or struct, so it would have been widened at some 
point before calling the function. So that example would give a 
misleading picture of what's involved.

> 
> No.  You are asking it to do something else - you are asking it to load 
> a _Bool from memory, not just convert it.

It loads from memory and converts it in one instruction; isn't that 
something? But this is pretty much what your godbolt link does, where 
you have to resort to using static variables, since for -O1 and above, 
locals are kept in registers:

       movzx   eax, BYTE PTR b[rip]

It seems there /is/ something I overlooked: the -S output of gcc/clang 
is less readable, since variable names disappear: they either are kept 
in registers (where you don't know which is which); or they are 
addressed by numeric offsets, and again you don't know what is what.

[toc] | [prev] | [next] | [standalone]


#387426

FromDavid Brown <david.brown@hesbynett.no>
Date2024-08-09 19:08 +0200
Message-ID<v95ieq$qh1q$1@dont-email.me>
In reply to#387416
On 09/08/2024 02:56, Bart wrote:
> On 08/08/2024 23:32, David Brown wrote:
>> On 08/08/2024 21:09, Bart wrote:
> 
>>> Sorry but my function is perfectly valid. It's taking a Bool value 
>>> and converting it to an int.
>>
>> No, it is not.
>>
>> Attempting to use the value of a non-static local variable that has 
>> not been initialised or assigned is undefined behaviour.  Your 
>> function is garbage.  No one can draw any conclusions about how 
>> meaningless code is compiled.
> 
> FFS. You really think that makes a blind bit of difference?

Yes, I do.

> A variable 
> is not initialised, so the bool->int code shown must be just random 
> rubbish generated by the compiler? You think I wouldn't spot if there 
> was something amiss?

You wrote C code that had something amiss!

How often are you going to do this?  Write some piece of meaningless 
crap with undefined behaviour or - at best - no observable behaviour at 
all, compile with silly choices of flags, and then make nonsensical 
claims about what compilers do or how C is defined?  How hard is it for 
you to actually write a C function that has defined behaviour that does 
what you want it to do?  Get step 1 of these tests right, and we won't 
have to keep repeating this stuff.

> 
> OK, let's initialise it and see what difference it actually makes. My 
> code is now this:
> 
>    #include <stdbool.h>
> 
>    void BC(void) {
>        _Bool b;
>        int i;
>        i=b;
>    }
> 
>    void DB(void) {
>        _Bool b=false;
>        int i;
>        i=b;
>    }
> 
> The output from gcc -O1 is this:
> 
> BC:
>          ret
> DB:
>          ret
> 
> There is no difference. 

There is a difference in the code.  One (BC) has no defined behaviour. 
The other (DB) has defined behaviour with no observable behaviour.  It's 
not a surprise that a compiler generates no code for either of them.

> So, even initialised, it tells me nothing about 
> what might be involved in bool->int conversion. It is useless.
> 

Agreed.  Nobody suggested your code above as a good idea.

> Now I'll try it with -O0 (line breaks added):
> 
> BC:
>          push    rbp
>          mov     rbp, rsp
> 
>          movzx   eax, BYTE PTR [rbp-1]
>          mov     DWORD PTR [rbp-8], eax
> 
>          nop
>          pop     rbp
>          ret
> DB:
>          push    rbp
>          mov     rbp, rsp
>          mov     BYTE PTR [rbp-1], 0
> 
>          movzx   eax, BYTE PTR [rbp-1]
>          mov     DWORD PTR [rbp-8], eax
> 
>          nop
>          pop     rbp
>          ret
> 
> Exactly the same code, except DB has an extra line to initialise that 
> value.
> 
> Are you surprised it is the same? I am 99% sure that you already knew 
> this, but were pretending that the code was meaningless, for reasons 
> that escape me.
> 

Instead of trolling with what you know, without doubt, are pointless 
straw men, why not apply a little thought and write functions that make 
sense?  Or look at the functions that I wrote?

The stuff you write is either meaningless, or pointless, or perhaps 
both.  I have no doubt that you know this fine.

So the big question is, why are you writing it?  Is it just to provoke 
me?  Is it because you want to confuse the OP and other readers?  Do you 
like pretending to be a fool?

I'm giving up trying to help you - at least until you show some hint of 
trying to learn.  I will still make posts pointing out when you write 
nonsense that might confuse or mislead others, but I'll stop trying to 
explain things unless you specifically ask.

[toc] | [prev] | [next] | [standalone]


#387469

FromBart <bc@freeuk.com>
Date2024-08-10 11:03 +0100
Message-ID<v97dsn$i03p$1@dont-email.me>
In reply to#387426
On 09/08/2024 18:08, David Brown wrote:
> On 09/08/2024 02:56, Bart wrote:
>> On 08/08/2024 23:32, David Brown wrote:
>>> On 08/08/2024 21:09, Bart wrote:
>>
>>>> Sorry but my function is perfectly valid. It's taking a Bool value 
>>>> and converting it to an int.
>>>
>>> No, it is not.
>>>
>>> Attempting to use the value of a non-static local variable that has 
>>> not been initialised or assigned is undefined behaviour.  Your 
>>> function is garbage.  No one can draw any conclusions about how 
>>> meaningless code is compiled.
>>
>> FFS. You really think that makes a blind bit of difference?
> 
> Yes, I do.
> 
>> A variable is not initialised, so the bool->int code shown must be 
>> just random rubbish generated by the compiler? You think I wouldn't 
>> spot if there was something amiss?
> 
> You wrote C code that had something amiss!
> 
> How often are you going to do this?  Write some piece of meaningless 
> crap with undefined behaviour or - at best - no observable behaviour at 
> all, compile with silly choices of flags, and then make nonsensical 
> claims about what compilers do or how C is defined?

What did I get wrong about that particular conversion?

I write such fragments of code for my own compilers a hundred times a day.

It only seems to cause a hoo-hah with your favourite compiler.

As for UB, what exactly is undefined about:

>>    void DB(void) {
>>        _Bool b=false;
>>        int i;
>>        i=b;
>>    }

> There is a difference in the code.  One (BC) has no defined behaviour. 
> The other (DB) has defined behaviour with no observable behaviour.

Ah. No observable behaviour.

This is indeed a problem with an optimising compiler, because it is in 
that mode that a compiler will detect that your code has no observable 
effects (other than in half a dozen ways I could mention, such as 
looking at the generated code!), and decides it's not going to bother 
producing it.

This is why I recommend -O0 with such compilers. Or better, use a 
simpler compiler.

(Mine for example have absolute no problem with meaningless fragments, 
so long as they satisfy language rules. They will even produce comment 
lines like these:

  ;------------------------------
   ...
  ;------------------------------

to more easily isolate a function body from entry/exit code.

For something available to everyone, then Tiny C is available on 
godbold.org.)


> not a surprise that a compiler generates no code for either of them.
> 
>> So, even initialised, it tells me nothing about what might be involved 
>> in bool->int conversion. It is useless.
>>
> 
> Agreed.  Nobody suggested your code above as a good idea.
> 
>> Now I'll try it with -O0 (line breaks added):
>>
>> BC:
>>          push    rbp
>>          mov     rbp, rsp
>>
>>          movzx   eax, BYTE PTR [rbp-1]
>>          mov     DWORD PTR [rbp-8], eax
>>
>>          nop
>>          pop     rbp
>>          ret
>> DB:
>>          push    rbp
>>          mov     rbp, rsp
>>          mov     BYTE PTR [rbp-1], 0
>>
>>          movzx   eax, BYTE PTR [rbp-1]
>>          mov     DWORD PTR [rbp-8], eax
>>
>>          nop
>>          pop     rbp
>>          ret
>>
>> Exactly the same code, except DB has an extra line to initialise that 
>> value.
>>
>> Are you surprised it is the same? I am 99% sure that you already knew 
>> this, but were pretending that the code was meaningless, for reasons 
>> that escape me.
>>
> 
> Instead of trolling with what you know, without doubt, are pointless 
> straw men, why not apply a little thought and write functions that make 
> sense?

When you are testing code fragments, they DON'T make sense. Hence -O0 to 
avoid having to soft-soap or cajole the compiler into producing relevant 
code.

It's to make life easier not harder. The only thing with -O0 is to learn 
to disregard the irrelevant bits. But at least YOU get to say what is 
irrelevant.


> I'm giving up trying to help you - at least until you show some hint of 
> trying to learn.

What the fuck are you on about?

I'm suggesting using -O0 because it is easier: you write code fragments 
without have to write a complete, meaningful program that has observable 
behaviour.

Which is quite hard to do; benchmaking code from an optimising compiler 
can be challenging, since it is easy for it to circumvent the very task 
you're trying to measure. Apparently, program runtime does not count as 
'observable behaviour' so it is not something that attempt is made to 
preserve.



>  I will still make posts pointing out when you write 
> nonsense that might confuse or mislead others, but I'll stop trying to 
> explain things unless you specifically ask.

So will I, to other people.

The set of tests posted by MS, compiler with optimising options with 
Clang, shed no light on bool to int conversion.

[toc] | [prev] | [next] | [standalone]


#387418

FromLawrence D'Oliveiro <ldo@nz.invalid>
Date2024-08-09 02:45 +0000
Message-ID<v93vsn$hjg3$3@dont-email.me>
In reply to#387405
On Thu, 8 Aug 2024 20:09:56 +0100, Bart wrote:

> But I suspect a long gaslighting session coming on, where you refute the
> evidence that everyone else can see!

A denial is not a refutation.

[toc] | [prev] | [next] | [standalone]


#387408

FromKeith Thompson <Keith.S.Thompson+u@gmail.com>
Date2024-08-08 12:42 -0700
Message-ID<87ttfu94yv.fsf@nosuchdomain.example.com>
In reply to#387390
Thiago Adams <thiago.adams@gmail.com> writes:
> On 07/08/2024 17:00, Dan Purgert wrote:
>> On 2024-08-07, Thiago Adams wrote:
[...]
>>> How about floating point?
>> Floating point is a huge mess, and has a few variations for
>> encoding;
>> though I think most C implementations use the one from the IEEE on 1985
>> (uh, IEEE754, I think?)
>
> I didn't specify properly , but my question was more about floating
> point registers. I think in this case they have specialized registers.

Who is "they"?

Some CPUs have floating-point registers, some don't.  C says nothing
about registers.

What exactly is your question?  Is it not already answered by reading
the "Conversions" section of the C standard?

-- 
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
void Void(void) { Void(); } /* The recursive call of the void */

[toc] | [prev] | [next] | [standalone]


#387409

FromThiago Adams <thiago.adams@gmail.com>
Date2024-08-08 17:34 -0300
Message-ID<v93a3t$6q7v$1@dont-email.me>
In reply to#387408
On 08/08/2024 16:42, Keith Thompson wrote:
> Thiago Adams <thiago.adams@gmail.com> writes:
>> On 07/08/2024 17:00, Dan Purgert wrote:
>>> On 2024-08-07, Thiago Adams wrote:
> [...]
>>>> How about floating point?
>>> Floating point is a huge mess, and has a few variations for
>>> encoding;
>>> though I think most C implementations use the one from the IEEE on 1985
>>> (uh, IEEE754, I think?)
>>
>> I didn't specify properly , but my question was more about floating
>> point registers. I think in this case they have specialized registers.
> 
> Who is "they"?
> 
> Some CPUs have floating-point registers, some don't.  C says nothing
> about registers.
> 
> What exactly is your question?  Is it not already answered by reading
> the "Conversions" section of the C standard?
> 


This part is related with the previous question about the origins of 
integer promotions.

We don't have "char" register or signed/unsigned register. But I believe 
we may have double and float registers. So float does not need to be 
converted to double.

There is no specif question here, just trying to understand the 
rationally behind the conversions rules.

[toc] | [prev] | [next] | [standalone]


#387410

FromBart <bc@freeuk.com>
Date2024-08-08 22:41 +0100
Message-ID<v93e2q$8put$1@dont-email.me>
In reply to#387409
On 08/08/2024 21:34, Thiago Adams wrote:
> On 08/08/2024 16:42, Keith Thompson wrote:
>> Thiago Adams <thiago.adams@gmail.com> writes:
>>> On 07/08/2024 17:00, Dan Purgert wrote:
>>>> On 2024-08-07, Thiago Adams wrote:
>> [...]
>>>>> How about floating point?
>>>> Floating point is a huge mess, and has a few variations for
>>>> encoding;
>>>> though I think most C implementations use the one from the IEEE on 1985
>>>> (uh, IEEE754, I think?)
>>>
>>> I didn't specify properly , but my question was more about floating
>>> point registers. I think in this case they have specialized registers.
>>
>> Who is "they"?
>>
>> Some CPUs have floating-point registers, some don't.  C says nothing
>> about registers.
>>
>> What exactly is your question?  Is it not already answered by reading
>> the "Conversions" section of the C standard?
>>
> 
> 
> This part is related with the previous question about the origins of 
> integer promotions.
> 
> We don't have "char" register or signed/unsigned register. But I believe 
> we may have double and float registers. So float does not need to be 
> converted to double.
> 
> There is no specif question here, just trying to understand the 
> rationally behind the conversions rules.

The rules have little to do with concrete machines with registers.

Your initial post showed come confusion about how conversions work. They 
are not performed 'in-place', any more than writing `a + 1` changes the 
value of `a`.

Take:

     int a; double x;

     x = (double)a;

The cast is implicit here but I've written it out to make it clear. My C 
compiler produces intermediate code like this before converting it to 
native code:

     push x   r64                   # r64 means float64
     fix      r64 -> i32
     pop  a   i32

I could choose to interprete this code just as it is. Then, in this 
execution model, there are no registers at all, only a stack that can 
hold data of any type.

The 'fix' instruction pops the double value from the stack, converts it 
to int (which involves changing both the bit-pattern, and the 
bit-width), and pushes it back onto the stack.

Registers come into it when running it directly on a real machine. But 
you seem more concerned with safety and correctness than performance, so 
there's probably no real need to look at actual generated native code.

That'll just be confusing (especially if you follow the advice to 
generate only optimised code).



[toc] | [prev] | [next] | [standalone]


Page 2 of 7 — ← Prev page 1 [2] 3 4 5 6 7  Next page →

Back to top | Article view | comp.lang.c


csiph-web