I want to convert a bool
into an int
. The "standard" option is:
static int F(bool b)
{
int i = Convert.ToInt32(b);
return i;
}
//ILSpy told me about this
public static int ToInt32(bool value)
{
if (!value)
{
return 0;
}
return 1;
}
This code generates following assembly:
<Program>$.<<Main>$>g__F|0_0(Boolean)
L0000: test cl, cl
L0002: jne short L0008
L0004: xor eax, eax
L0006: jmp short L000d
L0008: mov eax, 1
L000d: ret
As you might have noticed this is a questionable way (I think it is, I'm not an expert) of converting a bool
into an int
.
What I have tried
The hunt is for the following assembly which is generated by the GCC
:
code:
__attribute__((ms_abi))
int
f(bool b) {
int i;
i = (int)b;
return i;
}
asm:
f(bool):
movzx eax, cl
ret
- In the first step I combined the functions:
static int G(bool b)
{
int i = b == true ? 1 : 0;
return i;
}
I think it helped a bit (see the comments in code).
<Program>$.<<Main>$>g__G|0_1(Boolean)
L0000: test cl, cl
L0002: jne short L0007
L0004: xor eax, eax
L0006: ret ; This returns directly instead of jumping to RET instruction.
L0007: mov eax, 1
L000c: ret
- In the next step I tried to use
unsafe
tricks:
static unsafe int H(bool b)
{
int i = *(int*)&b;
return i;
}
this generates:
<Program>$.<<Main>$>g__H|0_2(Boolean)
L0000: mov [rsp+8], ecx ; it looks better but I can't get rid of this line
L0004: mov eax, [rsp+8] ; it looks better but I can't get rid of this line
L0008: movzx eax, al
L000b: ret
- In the next step I removed the temp variable (I thought it would help).
static unsafe int Y(bool b)
{
return *(int*)&b;
}
this generates the same ASM
:
<Program>$.<<Main>$>g__Y|0_3(Boolean)
L0000: mov [rsp+8], ecx
L0004: mov eax, [rsp+8]
L0008: movzx eax, al
L000b: ret
Question
As you can see I'm stuck here (I don't know how to remove the first 2 instructions). Is there a way of converting a bool
variable into an int
one?
Note
In case you want to play with example: here is the SharpLab link.
Benchmark results:
on x64/Release
for 5000000000
iterations:
- H() took
~1320ms
- F() took
~1610ms
- Included the code for benchmarking:
var w = new Stopwatch();
long r = 0;
for (int i = 0; i < 10; ++i)
{
w.Restart();
for (long j = 0; j < 5000000000; ++j)
{
F(true);
F(false);
}
w.Stop();
r += w.ElapsedMilliseconds;
Console.WriteLine(w.ElapsedMilliseconds);
}
Console.WriteLine("AV" + r / 10);