Deutsch   English   Français   Italiano  
<v92va5$4msg$1@dont-email.me>

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

Path: ...!feeds.phibee-telecom.net!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 18:29:40 +0100
Organization: A noiseless patient Spider
Lines: 82
Message-ID: <v92va5$4msg$1@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>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
Injection-Date: Thu, 08 Aug 2024 19:29:42 +0200 (CEST)
Injection-Info: dont-email.me; posting-host="0ec5f4cd8f82378826952c114447df93";
	logging-data="154512"; mail-complaints-to="abuse@eternal-september.org";	posting-account="U2FsdGVkX18Ctpq5Ef6df4aCBH2pU/Af"
User-Agent: Mozilla Thunderbird
Cancel-Lock: sha1:2flc3oNDgadQPqgn1AkfAyIO14Q=
Content-Language: en-GB
In-Reply-To: <20240808193203.00006287@yahoo.com>
Bytes: 3591

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.