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 6 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-10 17:10 -0700 |
| Message-ID | <87zfpj537h.fsf@nosuchdomain.example.com> |
| In reply to | #387474 |
Thiago Adams <thiago.adams@gmail.com> writes:
> Em 8/10/2024 1:14 PM, Bart escreveu:
>>>
>>> Bart, Does your compiler support the `bool` type, where the value
>>> is always either 1 or 0?
>> There is a bool type, but it is treated like unsigned char, so is
>> non-conforming.
>
> I do the same in my compiler , when I transpile from C99 to C89.
> I was thinking how to make it conforming.
> For instance on each write.
>
> bool b = 123; -> unsigned char b = !!(123);
>
> The problem this does not fix unions, writing on int and reading from char.
I don't think you need to fix that.
In the following, I'll refer to _Bool. The same type is also called
bool if you have `#include <stdbool.h>` *or* if you have a C23 compiler.
It's always going to be possible to use type punning (memcpy, pointer
casting, union) to force a representation other than 00000000 or
00000001 into a _Bool object.
The standard doesn't have a rule that says a _Bool object can only have
the value 0 or 1. It says that *conversion* to _Bool yields a result of
0 or 1. And yes, you have to deal with that if you're translating C99
or later to C90, for both explicit and implicit conversions.
Suppose you do something like this:
_Bool b;
*(unsigned char*)&b = 0xff; // assume sizeof (_Bool) == 1
int i = b;
What is the value of b?
Under C23 rules, _Bool has 1 value bit and N-1 (typically 7) padding
bits. Any non-zero padding bits *either* create a trap representation
(C23 calls it a non-value representation) *or* are ignored when
determining the value of the object.
(_Bool can have either 254 trap representations or none. It's possible
that it might have some different number of trap representations, but
that's unlikely.)
If 11111111 is a trap/non-value representation, the behavior of
`int i = b;` is undefined; setting i to 255 or -1 are two of many
possible behaviors. If the padding bits are ignored, it must set i to 1.
Experiment shows that gcc sets i to 255 (implying that it's a trap
representation) while clang sets i to 1 (which could imply that it's not
a trap representation, but that's still a possible result of UB).
Summary:
Conversion from any scalar type to _Bool is well defined, and must yield
0 or 1.
It's possible to force a representation other than 0 or 1 into a _Bool
object, bypassing any value conversion.
Conversion from _Bool to any scalar type is well defined if the
operand is a _Bool object holding a representation of 0 or 1.
Conversion from _Bool to any scalar type for an object holding some
representation other than 0 or 1 either yields 0 or 1 (depending
on the low-order bit) or has undefined behavior.
--
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-11 09:23 -0300 |
| Message-ID | <v9aafn$298lv$1@dont-email.me> |
| In reply to | #387475 |
Em 8/10/2024 9:10 PM, Keith Thompson escreveu:
> Thiago Adams <thiago.adams@gmail.com> writes:
>> Em 8/10/2024 1:14 PM, Bart escreveu:
>>>>
>>>> Bart, Does your compiler support the `bool` type, where the value
>>>> is always either 1 or 0?
>>> There is a bool type, but it is treated like unsigned char, so is
>>> non-conforming.
>>
>> I do the same in my compiler , when I transpile from C99 to C89.
>> I was thinking how to make it conforming.
>> For instance on each write.
>>
>> bool b = 123; -> unsigned char b = !!(123);
>>
>> The problem this does not fix unions, writing on int and reading from char.
>
> I don't think you need to fix that.
[....]
> Summary:
>
> Conversion from any scalar type to _Bool is well defined, and must yield
> 0 or 1.
I will fix in terns of expressions types.
- In this case cast to bool
- Assignment to bool
> It's possible to force a representation other than 0 or 1 into a _Bool
> object, bypassing any value conversion.
>
> Conversion from _Bool to any scalar type is well defined if the
> operand is a _Bool object holding a representation of 0 or 1.
>
> Conversion from _Bool to any scalar type for an object holding some
> representation other than 0 or 1 either yields 0 or 1 (depending
> on the low-order bit) or has undefined behavior.
I did a sample now..
#include <stdio.h>
int main() {
union {
int i;
_Bool b;
} data;
data.i = 123;
printf("%d", data.b);
}
it printed 123 not 1.
So I think the assignment and cast covers all/most cases.
(From some previous tests I thought this was printing 1)
The motivation for C89 in cake was not to support old compilers, but
generate code that is compatible with C++98. In this aspect bool was
already there in C++98.(This just gave me idea to add target c++98)
[toc] | [prev] | [next] | [standalone]
| From | Bart <bc@freeuk.com> |
|---|---|
| Date | 2024-08-11 13:30 +0100 |
| Message-ID | <v9aasg$2mfsi$1@dont-email.me> |
| In reply to | #387476 |
On 11/08/2024 13:23, Thiago Adams wrote:
> Em 8/10/2024 9:10 PM, Keith Thompson escreveu:
>> Thiago Adams <thiago.adams@gmail.com> writes:
>>> Em 8/10/2024 1:14 PM, Bart escreveu:
>>>>>
>>>>> Bart, Does your compiler support the `bool` type, where the value
>>>>> is always either 1 or 0?
>>>> There is a bool type, but it is treated like unsigned char, so is
>>>> non-conforming.
>>>
>>> I do the same in my compiler , when I transpile from C99 to C89.
>>> I was thinking how to make it conforming.
>>> For instance on each write.
>>>
>>> bool b = 123; -> unsigned char b = !!(123);
>>>
>>> The problem this does not fix unions, writing on int and reading from
>>> char.
>>
>> I don't think you need to fix that.
>
> [....]
>
>> Summary:
>>
>> Conversion from any scalar type to _Bool is well defined, and must yield
>> 0 or 1.
>
>
> I will fix in terns of expressions types.
>
> - In this case cast to bool
> - Assignment to bool
>
>> It's possible to force a representation other than 0 or 1 into a _Bool
>> object, bypassing any value conversion.
>>
>> Conversion from _Bool to any scalar type is well defined if the
>> operand is a _Bool object holding a representation of 0 or 1.
>>
>> Conversion from _Bool to any scalar type for an object holding some
>> representation other than 0 or 1 either yields 0 or 1 (depending
>> on the low-order bit) or has undefined behavior.
>
> I did a sample now..
>
> #include <stdio.h>
>
> int main() {
> union {
> int i;
> _Bool b;
> } data;
> data.i = 123;
> printf("%d", data.b);
> }
>
> it printed 123 not 1.
> So I think the assignment and cast covers all/most cases.
> (From some previous tests I thought this was printing 1)
That's little different from this example:
#include <stdio.h>
int main() {
union {
int i;
float b;
} data;
data.i = 123;
printf("%e", data.b);
}
I get some arbitrary float value printed. You're supposed to know what
you are doing with unions.
It's not something I'd worry about. If you're trying to make a safer C,
then you'd have to ban unions, or ban bools inside unions that could be
read out as a different type, or introduce tagged unions so that runtime
checking can be done.
[toc] | [prev] | [next] | [standalone]
| From | Thiago Adams <thiago.adams@gmail.com> |
|---|---|
| Date | 2024-08-11 14:16 -0300 |
| Message-ID | <v9arkh$2pvdf$1@dont-email.me> |
| In reply to | #387477 |
Em 8/11/2024 9:30 AM, Bart escreveu:
> On 11/08/2024 13:23, Thiago Adams wrote:
>> Em 8/10/2024 9:10 PM, Keith Thompson escreveu:
>>> Thiago Adams <thiago.adams@gmail.com> writes:
>>>> Em 8/10/2024 1:14 PM, Bart escreveu:
>>>>>>
>>>>>> Bart, Does your compiler support the `bool` type, where the value
>>>>>> is always either 1 or 0?
>>>>> There is a bool type, but it is treated like unsigned char, so is
>>>>> non-conforming.
>>>>
>>>> I do the same in my compiler , when I transpile from C99 to C89.
>>>> I was thinking how to make it conforming.
>>>> For instance on each write.
>>>>
>>>> bool b = 123; -> unsigned char b = !!(123);
>>>>
>>>> The problem this does not fix unions, writing on int and reading
>>>> from char.
>>>
>>> I don't think you need to fix that.
>>
>> [....]
>>
>>> Summary:
>>>
>>> Conversion from any scalar type to _Bool is well defined, and must yield
>>> 0 or 1.
>>
>>
>> I will fix in terns of expressions types.
>>
>> - In this case cast to bool
>> - Assignment to bool
>>
>>> It's possible to force a representation other than 0 or 1 into a _Bool
>>> object, bypassing any value conversion.
>>>
>>> Conversion from _Bool to any scalar type is well defined if the
>>> operand is a _Bool object holding a representation of 0 or 1.
>>>
>>> Conversion from _Bool to any scalar type for an object holding some
>>> representation other than 0 or 1 either yields 0 or 1 (depending
>>> on the low-order bit) or has undefined behavior.
>>
>> I did a sample now..
>>
>> #include <stdio.h>
>>
>> int main() {
>> union {
>> int i;
>> _Bool b;
>> } data;
>> data.i = 123;
>> printf("%d", data.b);
>> }
>>
>> it printed 123 not 1.
>> So I think the assignment and cast covers all/most cases.
>> (From some previous tests I thought this was printing 1)
>
> That's little different from this example:
>
> #include <stdio.h>
>
> int main() {
> union {
> int i;
> float b;
> } data;
> data.i = 123;
> printf("%e", data.b);
> }
>
> I get some arbitrary float value printed. You're supposed to know what
> you are doing with unions.
One of my tests led me to the wrong conclusion that reading a boolean
value would cause the compiler to add a conversion on read.
I did something wrong..I don't remember. I will try to keep all tests
next time.
But now, everything is back to normal.
union {
int i;
_Bool b;
} data;
data.b = 123;
printf("%d", data.b); //prints 1 as expected
union {
int i;
_Bool b;
} data;
data.i = 123;
printf("%d", data.b); //prints 123 as expected
> It's not something I'd worry about. If you're trying to make a safer C,
> then you'd have to ban unions, or ban bools inside unions that could be
> read out as a different type, or introduce tagged unions so that runtime
> checking can be done.
Something that could be done is to check in local context the last write
type is the same of last read. Then we can have a warning if they are
different.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <Keith.S.Thompson+u@gmail.com> |
|---|---|
| Date | 2024-08-11 13:38 -0700 |
| Message-ID | <87bk1yg5hc.fsf@nosuchdomain.example.com> |
| In reply to | #387476 |
Thiago Adams <thiago.adams@gmail.com> writes:
> Em 8/10/2024 9:10 PM, Keith Thompson escreveu:
>> Thiago Adams <thiago.adams@gmail.com> writes:
>>> Em 8/10/2024 1:14 PM, Bart escreveu:
>>>>>
>>>>> Bart, Does your compiler support the `bool` type, where the value
>>>>> is always either 1 or 0?
>>>> There is a bool type, but it is treated like unsigned char, so is
>>>> non-conforming.
>>>
>>> I do the same in my compiler , when I transpile from C99 to C89.
>>> I was thinking how to make it conforming.
>>> For instance on each write.
>>>
>>> bool b = 123; -> unsigned char b = !!(123);
>>>
>>> The problem this does not fix unions, writing on int and reading from char.
>> I don't think you need to fix that.
>
> [....]
>
>> Summary:
>> Conversion from any scalar type to _Bool is well defined, and must
>> yield
>> 0 or 1.
>
>
> I will fix in terns of expressions types.
>
> - In this case cast to bool
> - Assignment to bool
You need to cover all cases where a scalar value is converted to _Bool.
That includes (explicit) casts, assignment, initialization, argument
passing, and returning from a _Bool function.
Ideally you'd have one place in your code that handles conversions, but
you'll want to test all those cases and more.
>> It's possible to force a representation other than 0 or 1 into a _Bool
>> object, bypassing any value conversion.
>> Conversion from _Bool to any scalar type is well defined if the
>> operand is a _Bool object holding a representation of 0 or 1.
>> Conversion from _Bool to any scalar type for an object holding some
>> representation other than 0 or 1 either yields 0 or 1 (depending
>> on the low-order bit) or has undefined behavior.
>
> I did a sample now..
>
> #include <stdio.h>
>
> int main() {
> union {
> int i;
> _Bool b;
> } data;
> data.i = 123;
> printf("%d", data.b);
> }
>
> it printed 123 not 1.
I get 123 if I compile with gcc, 1 if I compile with clang.
Both results are valid.
> So I think the assignment and cast covers all/most cases.
> (From some previous tests I thought this was printing 1)
>
> The motivation for C89 in cake was not to support old compilers, but
> generate code that is compatible with C++98. In this aspect bool was
> already there in C++98.(This just gave me idea to add target c++98)
C++ may have different rules, which you can discuss in comp.lang.c++.
>
>
>
>
>
A lot of your articles have multiple blank lines at the end. Can you
try to avoid that?
--
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 | Bart <bc@freeuk.com> |
|---|---|
| Date | 2024-08-12 12:24 +0100 |
| Message-ID | <v9cre7$38lqf$2@dont-email.me> |
| In reply to | #387483 |
On 11/08/2024 21:38, Keith Thompson wrote: > Thiago Adams <thiago.adams@gmail.com> writes: >> - In this case cast to bool >> - Assignment to bool > > You need to cover all cases where a scalar value is converted to _Bool. > That includes (explicit) casts, Is there any other kind?
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <Keith.S.Thompson+u@gmail.com> |
|---|---|
| Date | 2024-08-09 13:26 -0700 |
| Message-ID | <87ikw9788w.fsf@nosuchdomain.example.com> |
| In reply to | #387433 |
Thiago Adams <thiago.adams@gmail.com> writes:
> Em 8/9/2024 2:20 PM, David Brown escreveu:
>> On 09/08/2024 12:57, Thiago Adams wrote:
>>> Em 8/8/2024 6:41 PM, Bart escreveu:
>>>> 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).
>>>>
>>>>
>>>>
>>>>
>>> This part was always clear to me:
>>>
>>> "They are not performed 'in-place', any more than writing `a + 1`
>>> changes the value of `a`."
>>>
>>> Lets take double to int.
>>>
>>> In this case the bits of double needs to be reinterpreted (copied
>>> to) int.
>>>
>>> So the answer "how it works" can be
>>>
>>> always/generally machine has a instruction to do this
>>>
>>> or.. this is defined by the IIE ... standard as ...
>>>
>>>
>> It would be helpful if you made more of an effort to write clearly
>> here. (We know you can do so when you want to.) It is very
>> difficult to follow what you are referring to here - what is "this
>> case" here? A conversion from a double to an int certainly does not
>> re-interpret or copy bits - like other conversions, it copies the
>> /value/ to the best possible extent given the limitations of the
>> types.
>
> Everything is a bit mixed up, but I'll try to explain the part about
> registers that I have in mind.
Why you keep talking about registers? The C standard does not talk
about registers, and the promotion rules are based on which *operations*
are available, not what kinds of registers a given CPU happens to have.
> In C, when you have an expression like char + char, each char is
> promoted to int. The computation then occurs as int + int.
Right. And the most important thing to keep in mind is that it works
that way *because the C standard says so*.
If you're looking for a rationale for this, it's probably because some
early C compilers were for target systems that didn't provide operations
on narrow types. (The PDP-11 does have instructions that operate on
8-bit bytes, but the arithmetic instructions operate only on 16-bit
words.) But the C standard rules apply to all conforming C
implementations. If a target CPU happens to provide a 1-byte add
instruction, a C compiler can't use it unless it can prove that the
result is consistent with C semantics.
Knowing why the C standard says what it says can be interesting, but
it's not necessarily directly useful.
> On the other hand, when you have float + float, it remains as float + float.
That's implementation-defined. Read the "Characteristics of floating
types <float.h>" section of the C standard (it's 5.2.5.3.3 in the N3220
draft) and look for FLT_EVAL_METHOD. If FLT_EVAL_METHOD (defined in
<float.h>) is 0, float operations are done in type float. If it's 1,
float operations are done in type double. If it's 2, all floating-point
operations are done in type long double.
> My guess for this design is that computations involving char are done
> using registers that are the size of an int.
Who says the target CPU even has registers, or that computations can't
be done directly on values in memory?
> But, float + float is not promoted to double, so I assume that the
> computer has specific float registers or similar operation
> instructions for float.
Again, some CPUs have floating-point registers and some do not. Those
that don't might store floating-point values in the same registers used
for integer values, applying different instructions to operate on them.
Of those that do have floating-point registers, some have registers that
can hold a double value (typically 64 bits); they may or may not be able
to treat a half-register as a 32-bot float value.
The rules in the C standard are, for the most part, based on the
capabilities of CPUs that existed when the standard was written, not
necessarily on modern CPUs (though there have been tweaks in later
editions).
> Regarding the part about signed/unsigned registers and operations, I
> must admit that I'm not sure. I was planning to check on Compiler
> Explorer, but I haven't done that yet.
>
> I can frame the question like this: Does the computer make a
> distinction when adding signed versus unsigned integers? Are there
> specific assembly instructions for signed versus unsigned operations,
> covering all possible combinations?
Maybe.
What is your goal here? Are you trying to understand the history behind
the rules given in the C standard, or trying to understand the rules
themselves, or both?
--
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-09 18:01 -0300 |
| Message-ID | <v9602l$60n0$1@dont-email.me> |
| In reply to | #387444 |
Em 8/9/2024 5:26 PM, Keith Thompson escreveu: > Thiago Adams <thiago.adams@gmail.com> writes: >> Em 8/9/2024 2:20 PM, David Brown escreveu: >>> On 09/08/2024 12:57, Thiago Adams wrote: >>>> Em 8/8/2024 6:41 PM, Bart escreveu: >>>>> 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). >>>>> >>>>> >>>>> >>>>> >>>> This part was always clear to me: >>>> >>>> "They are not performed 'in-place', any more than writing `a + 1` >>>> changes the value of `a`." >>>> >>>> Lets take double to int. >>>> >>>> In this case the bits of double needs to be reinterpreted (copied >>>> to) int. >>>> >>>> So the answer "how it works" can be >>>> >>>> always/generally machine has a instruction to do this >>>> >>>> or.. this is defined by the IIE ... standard as ... >>>> >>>> >>> It would be helpful if you made more of an effort to write clearly >>> here. (We know you can do so when you want to.) It is very >>> difficult to follow what you are referring to here - what is "this >>> case" here? A conversion from a double to an int certainly does not >>> re-interpret or copy bits - like other conversions, it copies the >>> /value/ to the best possible extent given the limitations of the >>> types. >> >> Everything is a bit mixed up, but I'll try to explain the part about >> registers that I have in mind. > > Why you keep talking about registers? The C standard does not talk > about registers, and the promotion rules are based on which *operations* > are available, not what kinds of registers a given CPU happens to have. > I use "register" to talk about how hardware works. >> In C, when you have an expression like char + char, each char is >> promoted to int. The computation then occurs as int + int. > > Right. And the most important thing to keep in mind is that it works > that way *because the C standard says so*. > > If you're looking for a rationale for this, it's probably because some > early C compilers were for target systems that didn't provide operations > on narrow types. (The PDP-11 does have instructions that operate on > 8-bit bytes, but the arithmetic instructions operate only on 16-bit > words.) But the C standard rules apply to all conforming C > implementations. If a target CPU happens to provide a 1-byte add > instruction, a C compiler can't use it unless it can prove that the > result is consistent with C semantics. > > Knowing why the C standard says what it says can be interesting, but > it's not necessarily directly useful. > >> On the other hand, when you have float + float, it remains as float + float. > > That's implementation-defined. Read the "Characteristics of floating > types <float.h>" section of the C standard (it's 5.2.5.3.3 in the N3220 > draft) and look for FLT_EVAL_METHOD. If FLT_EVAL_METHOD (defined in > <float.h>) is 0, float operations are done in type float. If it's 1, > float operations are done in type double. If it's 2, all floating-point > operations are done in type long double. > >> My guess for this design is that computations involving char are done >> using registers that are the size of an int. > > Who says the target CPU even has registers, or that computations can't > be done directly on values in memory? > >> But, float + float is not promoted to double, so I assume that the >> computer has specific float registers or similar operation >> instructions for float. > > Again, some CPUs have floating-point registers and some do not. Those > that don't might store floating-point values in the same registers used > for integer values, applying different instructions to operate on them. > Of those that do have floating-point registers, some have registers that > can hold a double value (typically 64 bits); they may or may not be able > to treat a half-register as a 32-bot float value. > > The rules in the C standard are, for the most part, based on the > capabilities of CPUs that existed when the standard was written, not > necessarily on modern CPUs (though there have been tweaks in later > editions). > >> Regarding the part about signed/unsigned registers and operations, I >> must admit that I'm not sure. I was planning to check on Compiler >> Explorer, but I haven't done that yet. >> >> I can frame the question like this: Does the computer make a >> distinction when adding signed versus unsigned integers? Are there >> specific assembly instructions for signed versus unsigned operations, >> covering all possible combinations? > > Maybe. > > What is your goal here? Are you trying to understand the history behind > the rules given in the C standard, or trying to understand the rules > themselves, or both? > both. I have fixed cake constant expressions that were not doing integer promotion correctly. So I implemented the conversion rules.(6.3.1.8 Usual arithmetic conversions) To implement the constant expression for instance (char)1234 I had to implement the cast rule "as script" creating the combinations of all types x types. I was trying to implement some cast without all combinations type x type then I started the topic to understand how cast works to try to emulate what hardware does using bits..but at the end I did all combinations then the C compiler that compiles by C compiler will do what is necessary. In the future I also planning creating a backend so I want to understand better the low level. Apart of that I like to understand how/why things works.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <Keith.S.Thompson+u@gmail.com> |
|---|---|
| Date | 2024-08-09 14:53 -0700 |
| Message-ID | <87r0ax5poi.fsf@nosuchdomain.example.com> |
| In reply to | #387449 |
Thiago Adams <thiago.adams@gmail.com> writes:
> Em 8/9/2024 5:26 PM, Keith Thompson escreveu:
>> Thiago Adams <thiago.adams@gmail.com> writes:
>>> Em 8/9/2024 2:20 PM, David Brown escreveu:
>>>> On 09/08/2024 12:57, Thiago Adams wrote:
>>>>> Em 8/8/2024 6:41 PM, Bart escreveu:
>>>>>> 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).
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>> This part was always clear to me:
>>>>>
>>>>> "They are not performed 'in-place', any more than writing `a + 1`
>>>>> changes the value of `a`."
>>>>>
>>>>> Lets take double to int.
>>>>>
>>>>> In this case the bits of double needs to be reinterpreted (copied
>>>>> to) int.
>>>>>
>>>>> So the answer "how it works" can be
>>>>>
>>>>> always/generally machine has a instruction to do this
>>>>>
>>>>> or.. this is defined by the IIE ... standard as ...
>>>>>
>>>>>
>>>> It would be helpful if you made more of an effort to write clearly
>>>> here. (We know you can do so when you want to.) It is very
>>>> difficult to follow what you are referring to here - what is "this
>>>> case" here? A conversion from a double to an int certainly does not
>>>> re-interpret or copy bits - like other conversions, it copies the
>>>> /value/ to the best possible extent given the limitations of the
>>>> types.
>>>
>>> Everything is a bit mixed up, but I'll try to explain the part about
>>> registers that I have in mind.
>> Why you keep talking about registers? The C standard does not talk
>> about registers, and the promotion rules are based on which *operations*
>> are available, not what kinds of registers a given CPU happens to have.
>
> I use "register" to talk about how hardware works.
I don't see how that makes sense. Not all CPUs have registers. For
CPUs that do have registers, some support operations directly on memory.
Register size does not constrain the set of operations that are
available; for example a CPU might have 64-bit registers and support
both 64-bit and 32-bit operations.
Registers are largely irrelevant.
[...]
--
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 | Keith Thompson <Keith.S.Thompson+u@gmail.com> |
|---|---|
| Date | 2024-08-09 12:03 -0700 |
| Message-ID | <8734nd8qn7.fsf@nosuchdomain.example.com> |
| In reply to | #387423 |
Thiago Adams <thiago.adams@gmail.com> writes:
[...]
> This part was always clear to me:
>
> "They are not performed 'in-place', any more than writing `a + 1`
> changes the value of `a`."
>
> Lets take double to int.
>
> In this case the bits of double needs to be reinterpreted (copied to) int.
The word "reinterpreted" usually refers to taking a given representation
(sequence of bits) and treating it as a value of a specified type
*without changing the bits*. (<OT>C++ even has "reintrepret_cast" as a
keyword.</OT>)
Converting from int to double does not reinterpret the bits. It creates
a new value that is mathematically equal (or nearly so) to the operand
value.
> So the answer "how it works" can be
>
> always/generally machine has a instruction to do this
>
> or.. this is defined by the IIE ... standard as ...
Do you mean the IEEE standard? As always, the C standard defines the
semantics of conversions. For an implementation that claims to conform
to IEEE floating-point standard (ISO/IEC 60559), the semantics are
specified more precisely.
--
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-09 16:22 -0300 |
| Message-ID | <v95q9m$2oa92$3@dont-email.me> |
| In reply to | #387434 |
Em 8/9/2024 4:03 PM, Keith Thompson escreveu: > Thiago Adams <thiago.adams@gmail.com> writes: > [...] >> This part was always clear to me: >> >> "They are not performed 'in-place', any more than writing `a + 1` >> changes the value of `a`." >> >> Lets take double to int. >> >> In this case the bits of double needs to be reinterpreted (copied to) int. > > The word "reinterpreted" usually refers to taking a given representation > (sequence of bits) and treating it as a value of a specified type > *without changing the bits*. (<OT>C++ even has "reintrepret_cast" as a > keyword.</OT>) > > Converting from int to double does not reinterpret the bits. It creates > a new value that is mathematically equal (or nearly so) to the operand > value. > >> So the answer "how it works" can be >> >> always/generally machine has a instruction to do this >> >> or.. this is defined by the IIE ... standard as ... > > Do you mean the IEEE standard? As always, the C standard defines the > semantics of conversions. For an implementation that claims to conform > to IEEE floating-point standard (ISO/IEC 60559), the semantics are > specified more precisely. > Yes. maybe the conversion double to int for instance, is related with truncation, and this is specified on IEEE. The inverse int to double is similar. For instance ULLONGMAX to double. I guess all computers languages works in the same way today because also hardware works following the floating point standards. -- We already have many topics in one...but I am adding one more. :D _Decimal32 , _Decimal64 etc.. C23 have these new types. I think it has to me emulated because it is not something implemented on hardware. C started as being something more hardware related, but now we have complex types, bool, _Decimal.. I think all these types are "emulated".
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2024-08-09 00:36 +0200 |
| Message-ID | <v93ha8$9vom$2@dont-email.me> |
| In reply to | #387409 |
On 08/08/2024 22: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. > > Stop trying to think about registers or implementations until you have understood the meaning of the conversions, as detailed in the C standards. Implementation details are just that - implementation details, which vary from target to target, compiler to compiler, and according to the circumstances and the rest of the surrounding code. In general, conversions try to preserve values (with the exceptions and limitations detailed in the standards). If that involves changing the underlying bit representations, then those changes are made. If no changes are needed, no changes will be made.
[toc] | [prev] | [next] | [standalone]
| From | Dan Purgert <dan@djph.net> |
|---|---|
| Date | 2024-08-08 14:08 +0000 |
| Message-ID | <slrnvb9kae.28a.dan@djph.net> |
| In reply to | #387381 |
On 2024-08-08, Stefan Ram wrote: > Dan Purgert <dan@djph.net> wrote or quoted: >>I don't know what happens when you're changing datatype lengths, but if >>they're the same length, it's just telling the compiler what the >>variable should be treated as (e.g. [8-bit] int to char) > > Casting doesn't tweak a value right where it sits, so you don't > have to stress about resizing memory. (It hands you an rvalue, > not an lvalue.) Yeah, I have to admit I've been driving myself mad trying to learn AVR-Assembly lately, so ... types don't exist :| -- |_|O|_| |_|_|O| Github: https://github.com/dpurgert |O|O|O| PGP: DDAB 23FB 19FA 7D85 1CC1 E067 6D65 70E5 4CE7 2860
[toc] | [prev] | [next] | [standalone]
| From | Lawrence D'Oliveiro <ldo@nz.invalid> |
|---|---|
| Date | 2024-08-09 02:42 +0000 |
| Message-ID | <v93vne$hjg3$2@dont-email.me> |
| In reply to | #387381 |
On 8 Aug 2024 12:44:46 GMT, Stefan Ram wrote: > The whole casting concept hails from Algol. Type conversions are as old as the concept of types themselves. Algol 68 introduced the term “coercion” for explicit type conversions.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <Keith.S.Thompson+u@gmail.com> |
|---|---|
| Date | 2024-08-07 13:08 -0700 |
| Message-ID | <87frrg9jud.fsf@nosuchdomain.example.com> |
| In reply to | #387379 |
Thiago Adams <thiago.adams@gmail.com> writes:
> How cast works?
> Does it changes the memory?
> For instance, from "unsigned int" to "signed char".
> Is it just like discarding bytes or something else?
It depends on the source and target types.
A cast is an explicit conversion. It takes a value of some type and
yields a value of some (other) type -- or of the same type. The
semantics of a conversion are not affected by whether it's done
explicitly or implicitly.
The rules depend on the source and target types, and are specified in
the standard, section 6.3 "Conversions". You'll need to read the whole
thing.
> For instance, any 4 bytes type, cast to 2 bytes type is just the lower
> 2 bytes?
>
> [A][B][C][D]
> ->
> [A][B]
For some combinations of type, a conversion *might* be implemented that
way. Converting a 4-byte float to a 2-byte short definitely does not.
Conversions between pointer types, and between a pointer and an integer
of the same size, are *typically* implemented by copying or
reinterpreting the bits, but that's not universal. An implementation
could have different representations, even different sizes, for pointers
of different types.
> I also would like to understand better signed and unsigned.
> There is no such think as "signed" or "unsigned" register, right?
> How about floating point?
The C standard has no concept of registers (the "register" keyword
notwithstanding). All conversions are defined in terms of values.
(Some CPUs have distinct floating-point registers, but that affect
the semantics of floating-point operations.) An implementation will use
registers and operations on them to implement the semantics defined in
the standard (assuming the target CPU has registers).
> The motivation problem.
> I have a union, with unsigned int, unsigned char etc.(all types)
> I need to execute a cast in runtime (like script).
> The problem is that this causes an explosion of combinations that I am
> trying to avoid.
I don't think you're going to be able to avoid it.
Again, read section 6.3 "Conversions" of the standard. It sounds like
you're going to have to explicitly cover all the cases in that section
(except for null pointer constants, which exist only in source code).
[...]
--
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 08:35 -0300 |
| Message-ID | <v92aha$3u7l7$2@dont-email.me> |
| In reply to | #387382 |
On 07/08/2024 17:08, Keith Thompson wrote:
> Thiago Adams <thiago.adams@gmail.com> writes:
>> How cast works?
>> Does it changes the memory?
>> For instance, from "unsigned int" to "signed char".
>> Is it just like discarding bytes or something else?
I also curious about how bool works.
Values converted to bool became 0 or 1.
When this conversion happens, at read or write? Both?
How much does it cost?
I also learned we cannot cast a pointer to nullptr_t.
But we can read a union with nullptr. In this case the value is 0
similar of what happens with bool.
Sample
----------------
#include <stdio.h>
struct value {
int type;
union{
unsigned int ui;
_Bool b;
typeof(nullptr) p;
} ;
};
int main(){
struct value v;
v.ui = 123;
printf("%d / ", v.ui); //123
printf("%d / ", v.b); //1
printf("%p", v.p); //(nil)
}
--------
Using compiler explorer to understand bool.
void f(int i)
{
bool b = i;
printf("%d / ", b);
}
cmp dword ptr [rbp - 4], 0 //i think it checks 0 here
setne al
and al, 1
mov byte ptr [rbp - 5], al
I think it convert at write in this case..but for union it converts
when we read. This is why
printf("%d / ", v.b); //1
prints 1
void f()
{
union {
unsigned int ui;
_Bool b;
} v;
v.ui = 123;
printf("%d / ", v.b);
}
Where b.b is converted to 1?
f:
push rbp
mov rbp, rsp
sub rsp, 16
mov dword ptr [rbp - 4], 123
mov al, byte ptr [rbp - 4]
and al, 1
movzx esi, al
lea rdi, [rip + .L.str]
mov al, 0
call printf@PLT
add rsp, 16
pop rbp
ret
I think is at
al, 1
so the compiler uses 123 & 1 to cast number to bool.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <Keith.S.Thompson+u@gmail.com> |
|---|---|
| Date | 2024-08-08 12:39 -0700 |
| Message-ID | <87y156953x.fsf@nosuchdomain.example.com> |
| In reply to | #387391 |
Thiago Adams <thiago.adams@gmail.com> writes:
> On 07/08/2024 17:08, Keith Thompson wrote:
>> Thiago Adams <thiago.adams@gmail.com> writes:
>>> How cast works?
>>> Does it changes the memory?
>>> For instance, from "unsigned int" to "signed char".
>>> Is it just like discarding bytes or something else?
>
> I also curious about how bool works.
>
> Values converted to bool became 0 or 1.
> When this conversion happens, at read or write? Both?
I don't know what you mean by that.
A conversion takes a value of some type and yields a value of some
(other) type. If the target type is bool, the result is false (0) if
the operand is equal to zero, true (1) otherwise.
A cast is simply an explicit conversion. Explict and implicit
conversions do the same thing. (Some conversions can only be done
explicitly.)
A converted value does not "become" 0 or 1; the conversion *yields*
0 or 1. The value of (bool)42 is 1, but 42 is still 42.
> How much does it cost?
It depends on what code the compiler generates; the language doesn't
address that. It could be free if the result isn't used and the
compiler optimizes it away.
[...]
--
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-08 18:40 -0400 |
| Message-ID | <v93hgg$9q8p$1@dont-email.me> |
| In reply to | #387391 |
Thiago Adams <thiago.adams@gmail.com> writes: ... > I also curious about how bool works. > > Values converted to bool became 0 or 1. > When this conversion happens, at read or write? Both? You can take a value obtained by reading an object, or a value produced by evaluating an expression, and convert that value to a different type. That value can later be stored in an object, or it could be used as one of the operands for an expression. The conversion isn't associated with either the read or the write. Many conversions occur implicitly, a cast is used to explicitly make a conversion occur. int x = 3; bool b = x; In the above code, an implicit conversion from int to bool occurs after reading the value of 3 from x, and occurs before writing to bool. b = !(bool)(x-3); In this code, the conversion occurs after the value of 3 is retrieved from x, and after 3 is subtracted from it. That result of 0 is then converted to bool, and then the ! operator is applied to it. Finally, the result is written to b. So you see, it doesn't make sense to connect the conversion with either the read or the write.
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <tr.17687@z991.linuxsc.com> |
|---|---|
| Date | 2024-08-11 17:15 -0700 |
| Message-ID | <86bk1yk35e.fsf@linuxsc.com> |
| In reply to | #387413 |
James Kuyper <jameskuyper@alumni.caltech.edu> writes:
> Thiago Adams <thiago.adams@gmail.com> writes:
> ...
>
>> I also curious about how bool works.
>>
>> Values converted to bool became 0 or 1.
>> When this conversion happens, at read or write? Both?
>
> You can take a value obtained by reading an object, or a value produced
> by evaluating an expression, and convert that value to a different type.
> That value can later be stored in an object, or it could be used as one
> of the operands for an expression. The conversion isn't associated with
> either the read or the write. Many conversions occur implicitly, a cast
> is used to explicitly make a conversion occur.
>
> int x = 3;
> bool b = x;
>
> In the above code, an implicit conversion from int to bool occurs after
> reading the value of 3 from x, and occurs before writing to bool.
>
> b = !(bool)(x-3);
>
> In this code, the conversion occurs after the value of 3 is retrieved
> from x, and after 3 is subtracted from it. That result of 0 is then
> converted to bool, and then the ! operator is applied to it. Finally,
> the result is written to b. So you see, it doesn't make sense to connect
> the conversion with either the read or the write.
The assignment statement
b = !(bool)(x-3);
performs two conversions. The (bool) cast converts an int value
to a bool value. The assignment to b converts the value of the !
subexpression (which is of type int) to bool before assigning it.
Assignment operators always convert the value being assigned to
the type of the assignment expression, even if the two types
are the same.
[toc] | [prev] | [next] | [standalone]
| From | gazelle@shell.xmission.com (Kenny McCormack) |
|---|---|
| Date | 2024-08-08 16:19 +0000 |
| Subject | Is there an audio book version (Was: how cast works?) |
| Message-ID | <v92r70$fd84$2@news.xmission.com> |
| In reply to | #387382 |
In article <87frrg9jud.fsf@nosuchdomain.example.com>, Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote: >Thiago Adams <thiago.adams@gmail.com> writes: >> How cast works? >> Does it changes the memory? >> For instance, from "unsigned int" to "signed char". >> Is it just like discarding bytes or something else? > >It depends on the source and target types. > >A cast is an explicit conversion. It takes a value of some type and >yields a value of some (other) type -- or of the same type. The >semantics of a conversion are not affected by whether it's done >explicitly or implicitly. > >The rules depend on the source and target types, and are specified in >the standard, section 6.3 "Conversions". You'll need to read the whole >thing. What if he is a Trumper and can't read? What then? -- Modern Conservative: Someone who can take time out from demanding more flag burning laws, more abortion laws, more drug laws, more obscenity laws, and more police authority to make warrantless arrests to remind us that we need to "get the government off our backs".
[toc] | [prev] | [next] | [standalone]
Page 6 of 7 — ← Prev page 1 2 3 4 5 [6] 7 Next page →
Back to top | Article view | comp.lang.c
csiph-web