Deutsch   English   Français   Italiano  
<v93pfg$c7b8$1@dont-email.me>

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

Path: ...!3.eu.feeder.erje.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: Fri, 9 Aug 2024 01:56:15 +0100
Organization: A noiseless patient Spider
Lines: 160
Message-ID: <v93pfg$c7b8$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> <v92va5$4msg$1@dont-email.me>
 <v9310a$4v1a$2@dont-email.me> <v93565$6ffo$1@dont-email.me>
 <v93h12$9vom$1@dont-email.me>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 8bit
Injection-Date: Fri, 09 Aug 2024 02:56:16 +0200 (CEST)
Injection-Info: dont-email.me; posting-host="a5ef0e336b797e59eb82473df0f29c2d";
	logging-data="400744"; mail-complaints-to="abuse@eternal-september.org";	posting-account="U2FsdGVkX19/gnT0KZBB5Z//1f116GUG"
User-Agent: Mozilla Thunderbird
Cancel-Lock: sha1:poG1JCTYCGjBAfxOjv5osTeA+/E=
In-Reply-To: <v93h12$9vom$1@dont-email.me>
Content-Language: en-GB
Bytes: 6063

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.