Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #387379 > unrolled thread
| Started by | Thiago Adams <thiago.adams@gmail.com> |
|---|---|
| First post | 2024-08-07 08:28 -0300 |
| Last post | 2024-08-07 23:03 +0000 |
| Articles | 20 on this page of 121 — 14 participants |
Back to article view | Back to comp.lang.c
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 →
| From | Keith Thompson <Keith.S.Thompson+u@gmail.com> |
|---|---|
| Date | 2024-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]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2024-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]
| From | Bart <bc@freeuk.com> |
|---|---|
| Date | 2024-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]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2024-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]
| From | Keith Thompson <Keith.S.Thompson+u@gmail.com> |
|---|---|
| Date | 2024-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]
| From | Lawrence D'Oliveiro <ldo@nz.invalid> |
|---|---|
| Date | 2024-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]
| From | Keith Thompson <Keith.S.Thompson+u@gmail.com> |
|---|---|
| Date | 2024-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]
| From | James Kuyper <jameskuyper@alumni.caltech.edu> |
|---|---|
| Date | 2024-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]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2024-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]
| From | Keith Thompson <Keith.S.Thompson+u@gmail.com> |
|---|---|
| Date | 2024-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]
| From | Tim Rentsch <tr.17687@z991.linuxsc.com> |
|---|---|
| Date | 2024-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]
| From | Keith Thompson <Keith.S.Thompson+u@gmail.com> |
|---|---|
| Date | 2024-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]
| From | Tim Rentsch <tr.17687@z991.linuxsc.com> |
|---|---|
| Date | 2024-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]
| From | Bart <bc@freeuk.com> |
|---|---|
| Date | 2024-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]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2024-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]
| From | Bart <bc@freeuk.com> |
|---|---|
| Date | 2024-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]
| From | Lawrence D'Oliveiro <ldo@nz.invalid> |
|---|---|
| Date | 2024-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]
| From | Keith Thompson <Keith.S.Thompson+u@gmail.com> |
|---|---|
| Date | 2024-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]
| From | Thiago Adams <thiago.adams@gmail.com> |
|---|---|
| Date | 2024-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]
| From | Bart <bc@freeuk.com> |
|---|---|
| Date | 2024-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