используйте ((c1^c2) & ~32), чтобы проверить, являются ли c1 и c2 одним и тем же символом в разных случаях


Я видел такой код

if( ((c1^c2) & ~32)==0 )
{
  ...
}

В этом фрагменте кода, вероятно, означает, что если утверждение if истинно, то c1 и c2 являются одним и тем же символом в разных случаях, что означает, что один из них находится на расстоянии +32 или -32 от другого. Почему это так?

Я проверил себя и обнаружил, что в некоторых случаях это правда, а в других нет:
printf("%d", (65^97)& ~32);   //output is 0. right
printf("%d", (97^65)& ~32);   //output is 0. right

printf("%d", (50^82)& ~32);   //output is 64!! not the same though 82-50=32

Почему это? что же в этом волшебного?

1   3  

1 ответ:

(c1^c2) & ~32) xors c1 и c2, результат содержит биты, которые находятся в обоих символах и & с ~32 очищает (игнорирует) бит 5. (Он обнуляется независимо от того, был ли он одинаковым в обоих случаях или нет). Сравнивая это с нулем, проверяет, все ли биты, отличные от bit 5, одинаковы.

Это можно использовать, чтобы проверить, равны ли 2 буквы, игнорируя их регистр в представлении ascii, если вы уверены, что по крайней мере c1 или c2 является допустимым латинским символом(a-z, A-Z).

Чтобы понять это, давайте выберите 2 символа с разным регистром и сравните их:

       +---+---+---+---+---+---+---+---+
a      | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 1 |
       +---+---+---+---+---+---+---+---+
         |   x   |   |   |   |   |   |
       +---+---+---+---+---+---+---+---+
A      | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 |
       +---+---+---+---+---+---+---+---+

       +---+---+---+---+---+---+---+---+
a ^ A  | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
       +---+---+---+---+---+---+---+---+

       +---+---+---+---+---+---+---+---+
32     | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
       +---+---+---+---+---+---+---+---+

       +---+---+---+---+---+---+---+---+
~32    | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 1 |
       +---+---+---+---+---+---+---+---+

       +---+---+---+---+---+---+---+---+
&      | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
       +---+---+---+---+---+---+---+---+

Вы можете попробовать то же самое с j v/s J или t v/s z. Поэтому здесь нет никакой магии, только эта логика.

Иногда это условие также записывается как:

if (ch1 == ch2 || (ch1 ^ 32) == ch2)
{
  ...
}