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.