Я знаю, 42 - ответ на все, но как черт 42
результат этого?
int x = -(~'+'|0xAB^1337); //42
Я знаю, 42 - ответ на все, но как черт 42
результат этого?
int x = -(~'+'|0xAB^1337); //42
Чтобы понять, что происходит, вы должны посмотреть на двоичное представление значений в этом выражении. Но перед этим давайте посмотрим, как символы преобразуются в целые числа и какие побитовые операторы используются здесь.
'+'
символ эквивалентен целочисленному значению 43
- вы можете проверить его, отбросив его до целого числа или используя Convert.ToInt32('+')
.
0xAB
представляет собой шестнадцатеричный литерал, который представляет десятичное значение 171
.
И последнее, что вы должны здесь понимать, это побитовые операторы:
~
побитовое NOT - оператор смотрит на двоичное представление значений выражения и выполняет побитовое отрицание на нем. Любая цифра, которая равна 1 в выражении, становится 0 в результате. Любая цифра, которая равна 0 в выражении, становится результатом 1.|
побитовое ИЛИ - смотрит на двоичное представление значений двух выражений и выполняет побитовое ИЛИ на них. Каждый раз, когда любое из выражений имеет 1 в цифре, результат будет иметь 1 в этой цифре. В противном случае результат будет иметь 0 в этой цифре.^
побитовый XOR - смотрит на двоичное представление значений двух выражений и выполняет побитовое исключающее ИЛИ действие на них. Когда один и только один из выражений имеет 1 в цифре, результат имеет 1 в этой цифре. В противном случае результат будет иметь 0 в этой цифре.Теперь все выражения выглядят как -(NOT(43) OR (171 XOR 1337))
. Перейдем к двоичному представлению этих чисел и операций:
Binary | Decimal | Comments
00000000000000000000000000101011 | 43 | '+'
11111111111111111111111111010100 | -44 | NOT 43 // bits are inverted
00000000000000000000000010101011 | 171 | 0xAB
00000000000000000000010100111001 | 1337 |
00000000000000000000010110010010 | 1426 | 171 XOR 1337 // different bits produce 1
11111111111111111111111111010100 | -44 | NOT 43
00000000000000000000010110010010 | 1426 | 171 XOR 1337
11111111111111111111111111010110 | -42 | -44 OR 1426 // 0 only if both bits are 0
00000000000000000000000000101010 | 42 | -(-42)
~'+'
, который является двоичным NOT на значении ascii '+'
= > -440xAB^1337
(двоичный XOR) = > 1426-44|1426
(двоичный OR) = > -42-42
(арифметическое отрицание) = > 42Ну, пусть шаг за шагом будет декодироваться:
int x = -(~'+'|0xAB^1337) ==
-((~'+') | 0xAB ^ 1337) == // '+' is char with ASCII code 43
-((~43)) | 0xAB ^ 1337) ==
-(0xFFFFFFD4 | 0xAB ^ 0x539) ==
-(0xFFFFFFD6) == // negation is binary complement + 1
(~0xFFFFFFD6 + 1) ==
42
Преобразование в hex обеспечивает относительно простой подход к выполнению двоичных вычислений вручную:
'+'
равен 0x2B или 00101011
в двоичном формате0x2B
- 0xFFFFFFD4
^
имеет более высокий приоритет, чем OR |
, поэтому 0xAB
сначала получает XOR-ed с 1337 (1337 - 0x539
)000010101011 ^ 010100111001 = 010110010010
, или 0x592
0xFFFFFFD4
и 0x00000592
создает 0xFFFFFD6
0x0000002A
, который равен 42 в десятичной форме.