| Deutsch English Français Italiano |
|
<v9316l$4msg$2@dont-email.me> View for Bookmarking (what is this?) Look up another Usenet article |
Path: ...!2.eu.feeder.erje.net!feeder.erje.net!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: Bart <bc@freeuk.com>
Newsgroups: comp.lang.c
Subject: Re: how cast works?
Date: Thu, 8 Aug 2024 19:01:56 +0100
Organization: A noiseless patient Spider
Lines: 130
Message-ID: <v9316l$4msg$2@dont-email.me>
References: <v8vlo9$2oc1v$1@dont-email.me> <slrnvb7kis.28a.dan@djph.net>
<v929ah$3u7l7$1@dont-email.me> <v92gt1$e1l$1@dont-email.me>
<20240808193203.00006287@yahoo.com> <v92va5$4msg$1@dont-email.me>
<v930ga$4mni$1@dont-email.me>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 8bit
Injection-Date: Thu, 08 Aug 2024 20:01:57 +0200 (CEST)
Injection-Info: dont-email.me; posting-host="0ec5f4cd8f82378826952c114447df93";
logging-data="154512"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/j5zc3wj/hxbqpYLZH669j"
User-Agent: Mozilla Thunderbird
Cancel-Lock: sha1:zbi0XHzIOztLs8Rev9wiw5J/z6w=
Content-Language: en-GB
In-Reply-To: <v930ga$4mni$1@dont-email.me>
Bytes: 5688
On 08/08/2024 18:50, Thiago Adams wrote:
> On 08/08/2024 14: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:
>>
>> 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.
>>
>> With optimisation turned on, even at -O1, it produces this:
>>
>> ret
>>
>> That strikes me as rather less enlightening!
>>
>> Meanwhile your foo_b2i function contains this optimised code:
>>
>> mov eax, edi
>> ret
>>
>> The masking and widening is not present. Presumably, it is taking
>> advantage of the fact that a _Bool argument will be converted and
>> widened to `int` at the callsite even though the parameter type is
>> also _Bool. So the conversion has already been done.
>>
>> You will see this if writing also a call to foo_b2i() and looking at
>> the /non-elided/ code.
>>
>> The unoptimised code for foo_b2i is pretty awful (like masking twice,
>> with a pointless write to memory between them). But sometimes with gcc
>> there is no sensible middle ground between terrible code, and having
>> most of it eliminated.
>>
>> The unoptimised code from my C compiler for foo_b2i, excluding
>> entry/exit code, is:
>>
>> movsx eax, byte [rbp + foo_b2i.x]
>>
>> My compiler assumes that a _Bool type already contains 0 or 1.
>>
>>
>>
>
> If you are doing constant expression in your compiler, then you have the
> same problem (casts) I am solving in cake.
>
> For instance
> static_assert((unsigned char)1234 == 210);
>
> is already working in my cake. I had to simulate this cast.
>
> Previously, I was doing all computations with bigger types for constant
> expressions. Then I realize compile time must work as the runtime.
>
> 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;
>
>
> I am also checking all wraparound and overflow in constant expressions.
> I have a warning when the computed value is different from the math value.
In my C compiler I have no constexpr (don't know why you got that
impression). And I don't check that initialisers for integer types
overflow their destination.
This is because within the language in general:
char c; int i;
c = i;
Such an assignment is not checked at runtime (and I don't know if this
can be warned against, or if a runtime check can be added).
This is just how C works: too-large values are silently truncated (there
are worse aspects of the language, like being able to do `int i;
(&i)[12345];`).
But you are presumably superimposing a new stricter language on top. In
the case, if my `c = i` assignment was not allowed, how do I get around
that; by a cast?