Немного магии bool

20

Вызов

Учитывая следующий метод C #:

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

Укажите значения aи bтак, чтобы они trueвозвращались.

Выигрышное условие

Первая запись, которая может предоставить правильные аргументы, чтобы заставить данный метод оценивать, trueвыигрывает.

актер
источник
4
Добро пожаловать в PPCG! Для всех испытаний здесь необходим объективный критерий выигрыша, чтобы победитель мог быть выбран при наличии нескольких заявок. Кажется, здесь может быть только одно решение, поэтому эта задача может не подходить для PPCG. Для будущих испытаний позвольте мне порекомендовать «песочницу», где вы можете получить обратную связь до того, как испытание будет запущено.
Мартин Эндер
2
Мета-дискуссия разбита на предмет того, находятся ли в теме вопросы программирования без дополнительных критериев выигрыша , а противоречивые ответы поддерживаются. Я бы предпочел оставить вопросы открытыми, когда они не решены, поэтому я голосую, чтобы вновь открыть. Если у вас есть мнения, пожалуйста, внесите их в обсуждение.
xnor
2
@DenkerAffe Я не думаю, что какая-либо из четырех очевидных комбинаций параметров работает.
Мартин Эндер
3
Предполагая, что есть верный ответ, это отличный вопрос, независимо от того, соответствует ли он тому, что мы обычно рассматриваем по теме. + 1. Я думаю, что одна из причин, по которой мы обычно не рассматриваем подобные вопросы по этой теме, заключается в том, что каждый второй вопрос, который я видел, был задан новичком, и ответ был ослепительно очевиден.
Уровень Река St
5
@ Видишь, вот почему «первое правильное решение» может быть не самой лучшей идеей. Вы можете получить неинтересное, но работающее решение, которое просто путается с некоторыми внутренностями через рефлексию, и тогда ни у кого нет стимула искать более интересное решение без рефлексии.
Мартин Эндер

Ответы:

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));
}

Это печатается Trueдля меня с реализацией C #, которая поставляется с Visual Studio 2015. Я на самом деле не знаю никакого C #, но я решил, что попробую написать код на C и посмотреть, сработает ли он. Я надеялся, что компилятор предположит, что True всегда представлен как 1, и использует побитовое AND. В режиме отладки это действительно так (он работал и с Release). Он использует побитовое И для первого условия и два сравнения с нулем для второго:

            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
источник
Удивительный! Я был абсолютно уверен, что это невозможно сделать
edc65
Я пробовал то же самое, но, похоже, он не работает в Mono под Linux.
jimmy23013
Это будет зависеть не от компилятора C # (в настоящее время Roslyn от MS), а скорее от JIT-компилятора (в настоящее время RyuJIT от MS). Хотя IL, создаваемый компилятором C #, также может влиять на работу JIT.
Боб