Подробнее
main.c 1 #include <stdio.h> 2 3 int main() 4 ’ { 5 - printf("%i %i %c %1 %1 %С %1 %1 %С %1 %1 6 s'+'9'9 // 159 7 // 7 8 '9*- 2 , // всё ещё 7 9 '9*- 2 , // автохрен, 55 10 - ' 5'+ 2 , // 55 0 °а°) -1 — 1-1 11 ' 5' + 2 , // а, не, норм, 7 12 // единичка 13 0 *'1', // нолик 14 ,0,*,1,J // ну слава богу, нолик 15 '1* * * 1', // 2401 щ(° щ) 16 // верни, мне. мой. нолик. 17 "Л\А'У )_/"*); 18 19 // да пошло оно всё, буду проституткой 20 21 return 0; 22 } 23 V / Я 159 7 7 55 55 7 1 О О 2401 2352 \ ('У ) / ...Program finished with exit code 0 Press ENTER to exit console.
it-юмор,geek,Прикольные гаджеты. Научный, инженерный и айтишный юмор
Еще на тему
Во-вторых, как завещали нам предки "факты > лулзы". А то ну что это за хурма такая, что каждый второй рофл это или самое стереотипное смещно потому что автор не в теме но делает вид что в теме, или самое стереотипное смещно потому что атор в теме но пытается продать это тем кто не в теме
соус: https://habr.com/ru/post/161205/
и всё
Тип '9' - int, а не char - элементарно. int - signed int, а char - не обязательно signed char, может быть и unsigned char - элементарно. В printf char автоматически кастуется до int, а в scanf нельзя путать int* и char* - элементарно.
В JS плюс кастует операнды к String, кроме случая, когда оба операнда - числа, а минус - к Number, и это настолько же элементарно.
Фактически взяли уникальное забавное совпадение, чтобы еще больше запутать читателя. В си есть проблемы из-за ручной работы с памятью, но самовольное, неинтуитивное и непонятное преобразование символов и чисел - этим си точно не страдает.
и тут стоило бы сказать: он этим наслаждается
С наслаждается поистину свободной арифметикой. Особенно адресной.
Ну и интерпретацией, да. Тут мы как раз видим пример, как можно интерпретировать одни и те же значения по-разному. И это ещё очень лайт. А вот когда начинается каст указателя одного типа на другой, вот там может начаться такая магия...
Хотя, один хрен ....
Вся магия в том, какими числами кодируются символы цифр
'0' - 0x30 - 48
'1' - 0x31 - 49
'2' - 0x32 - 50
'3' - 0x33 - 51
'4' - 0x34 - 52
'5' - 0x35 - 53
'6' - 0x36 - 54
'7' - 0x37 - 55
'8' - 0x38 - 56
'9' - 0x39 - 57
И в том, что значат эти закорючки в printf
%i - интерпретировать байты как число(3, 14, 15)
%с - интерпретировать байты как символ('W', 'o', 'r', 'l', 'd')
И дальше этот фокусник просто жонглирует этими двумя, по сути, несложными инструментами:
1) число: '1' + '5' + '9'
Тут просто подобраны такие символы, коды которых случайно суммируются в "такое же число"
0x31 + 0x35 + 0x39 = 0x9f = 159
2) число: '9' - '2'
Коды символов цифр отличаются ровно на 0x30. Общая часть при вычитании просто сокращается
0x39 - 0x32 = 0x7 = 7
3) символ: '9' - 2
Тут не та же семерка, что в (2). В (2) было число, а сейчас символ
0x39 - 2 = 0x37 = '7'
4) число: '9' - 2
Выражение то же что и в (3), но в (3) данные интерпретировались как символ, а тут как число
0x39 - 2 = 0x37 = 55
5) число: '5' + 2
0x35 + 2 = 0x37 = 55
6) символ: '5' + 2
Выражение то же что и в (5), но в (5) данные интерпретировались как число, а тут как символ
0x35 + 2 = 0x37 = 55 = 'a'
7) число: 1 * 1
1 * 1 = 1
8) число: 0 * '1'
0 * 0x31 = 0
9) символ: '0' * '1'
Тут ноль получился неспроста. Если перемножить коды символов, то получится переполнение. Если не вдаваться в подробности, то можно думать об этом как будто из результирующего числа возьмутся только две последние цифры
0x30 * 0x31 = 0x930 -> 0x30 = '0'
10) число: '1' * '1'
0x31 * 0x31 = 0x961 = 2401
11) символ: '1' * '0'
Выражение почти то же что и в (9), но в (9) данные интерпретировались как символ, а тут как число
0x30 * 0x31 = 0x930 = 2352