Trochę magii bool

20

Wyzwanie

Biorąc pod uwagę następującą metodę C #:

private static bool Test(bool a, bool b)
{
    if (a && b) return false;
    if (a) if (b) return true;
    return false;
}

Dostarczyć wartości ai btak, że truenie jest zwracana.

Warunki wygranej

Pierwszy wpis, który może podać poprawne argumenty, aby dana metoda oceniła truewygrane.

aktor
źródło
4
Witamy w PPCG! Wszystkie wyzwania tutaj wymagają obiektywnego kryterium wygranej, aby zwycięzca mógł zostać wybrany, jeśli jest wiele zgłoszeń. Wydaje się, że może istnieć tylko jedno rozwiązanie, więc to wyzwanie może nie pasować do PPCG. W przypadku przyszłych wyzwań pozwól mi polecić piaskownicę, w której możesz uzyskać informacje zwrotne, zanim wyzwanie zostanie wprowadzone w życie.
Martin Ender
2
Meta dyskusja jest podzielona na temat tego, czy zagadki programistyczne bez dodatkowych kryteriów wygranej dotyczą tematu , a sprzeczne odpowiedzi są oceniane. Wolę pozostawić pytania otwarte, gdy są nierozstrzygnięte, więc głosuję za ponownym otwarciem. Jeśli masz opinie, dodaj je do dyskusji.
xnor
2
@DenkerAffe Nie sądzę, żeby któraś z czterech oczywistych kombinacji parametrów działała.
Martin Ender
3
przy założeniu, że istnieje prawidłowa odpowiedź, jest to doskonałe pytanie, niezależnie od tego, czy pasuje do tego, co zwykle rozważamy na dany temat. + 1. Myślę, że jednym z powodów, dla których zwykle nie zastanawiamy się nad takimi pytaniami na ten temat, jest to, że każde inne pytanie, które widziałem w ten sposób, było zadawane przez początkującego, a odpowiedź była wręcz oczywista.
Level River St
5
@Widi Zobacz, dlatego „pierwsze prawidłowe rozwiązanie” może nie być najlepszym pomysłem. Możesz uzyskać nieciekawe, ale działające rozwiązanie, które po prostu miesza się z niektórymi elementami wewnętrznymi poprzez odbicie, a następnie nie ma zachęty, aby ktoś szukał bardziej interesującego rozwiązania bez refleksji.
Martin Ender

Odpowiedzi:

20
static void Main(string[] args)
{
    bool a, b;
    unsafe
    {
        int* pa = (int*)&a;
        int* pb = (int*)&b;
        *pa = 1;
        *pb = 2;
    }

        Console.Write(Test(a, b));
}

To drukuje Truedla mnie z implementacją C #, która jest dostarczana z Visual Studio 2015. Właściwie nie znam żadnego C #, ale pomyślałem, że spróbuję napisać trochę kodu C i sprawdzić, czy to zadziała. Miałem nadzieję, że kompilator przyjmie, że True jest zawsze reprezentowany jako 1 i użyje bitowego AND. W trybie debugowania tak właśnie jest (działało to również w wersji Release). Wykorzystuje bitowe AND dla pierwszego warunku i dwa porównania do zera dla drugiego:

            if (a && b) return false;
002C2E92  movzx       eax,byte ptr [ebp-3Ch]  
002C2E96  movzx       edx,byte ptr [ebp-40h]  
002C2E9A  and         eax,edx  
002C2E9C  and         eax,0FFh  
002C2EA1  mov         dword ptr [ebp-44h],eax  
002C2EA4  cmp         dword ptr [ebp-44h],0  
002C2EA8  je          002C2EB2  
002C2EAA  xor         edx,edx  
002C2EAC  mov         dword ptr [ebp-48h],edx  
002C2EAF  nop  
002C2EB0  jmp         002C2EE4  
            if (a) if (b) return true;
002C2EB2  movzx       eax,byte ptr [ebp-3Ch]  
002C2EB6  mov         dword ptr [ebp-4Ch],eax  
002C2EB9  cmp         dword ptr [ebp-4Ch],0  
002C2EBD  je          002C2EDC  
002C2EBF  movzx       eax,byte ptr [ebp-40h]  
002C2EC3  mov         dword ptr [ebp-50h],eax  
002C2EC6  cmp         dword ptr [ebp-50h],0  
002C2ECA  je          002C2EDC  
002C2ECC  mov         eax,1  
002C2ED1  and         eax,0FFh  
002C2ED6  mov         dword ptr [ebp-48h],eax  
002C2ED9  nop  
002C2EDA  jmp         002C2EE4  
            return false;
002C2EDC  xor         edx,edx  
002C2EDE  mov         dword ptr [ebp-48h],edx  
002C2EE1  nop  
002C2EE2  jmp         002C2EE4  
        }
002C2EE4  mov         eax,dword ptr [ebp-48h]  
002C2EE7  lea         esp,[ebp-0Ch]  
002C2EEA  pop         ebx  
002C2EEB  pop         esi  
002C2EEC  pop         edi  
002C2EED  pop         ebp  
002C2EEE  ret  
feersum
źródło
Niesamowity! Byłem całkowicie pewien, że nie da się tego zrobić
edc65
Próbowałem tego samego, ale wydaje się, że nie działa w Mono pod Linuksem.
jimmy23013
Byłoby to zależne nie od kompilatora C # (obecnie Roslyn od MS), ale raczej od kompilatora JIT (obecnie RyuJIT od MS). Chociaż generowany przez kompilator C # IL może również wpływać na działanie JIT.
Bob