je_suis_la_vie: (La Vie)
[personal profile] je_suis_la_vie
Надихнувся І. Бігдановим постом...

Що виведе Сішний код наведений нижче?

main() {

        printf(&unix["\021%six\012\0"], (unix)["drop"]+"gun"-0x71);

}

Колись - років чи з п'ять, чи шість тому - читав дуже добрий підручник. Французькою (коли б вона мені ще згодилася? :)), і лише у ньому зустрічав цю задачу. Більше ніде не попадалася, окрім як на одній співбесіді у нашому манюньому Кішлачку. :)


Відповідь літерами білого кольору, щоб прочитати треба виділити текст.

---

Індексні оператори підкоряються тим же арифметичним законам, які діють в арифметиці: від перестановки доданків сума не змінюється; від перестановки співмножників добуток не змінюється.
Це перестановочний (комутативний) закон.


Скажімо у нас є масив "x" з індексом "i" - x[i].

Запис x[i] повністю відповідає запису *(x+i), де ми беремо назву масива "x", яка є адресою початку масива, розіменовуємо його - "*" і вказуємо указкою на місце у масиві під номером "i".
Те ж саме ми отримаємо, написавши *(i+x), і навіть якщо ви запишете i[x] - ви отримаєте той же результат, що і від x[i]. :)

За такі збочення, на мою думку, у практичному програмуванні треба бити до памороків, але для навчання та настанови вони дуже корисні. Тож, продовжуємо. :)))


Константа "unix" це наперед визначена константа будь якого компілятора для UNIX-ової архітектури.
У числовому вираженні це просто "1" (одиничка).
Тож, ми можемо переписати завдання наступним чином:
printf(&1["\021%six\012\0"], (1)["drop"]+"gun"-0x71);


Відповідно до перестановочного закону додавання, що ми згадували вище, 1["\021%six\012\0"] - те ж саме,
що і "\021%six\012\0"[1] а (1)["drop"] - те ж саме, що й "drop"[1].

Тобто &1["\021%six\012\0"] - це адреса символу “%”.
Так ми отримуємо указку на рядок, що починається з "%".
А "drop"[1] - це указка на символ “r”.
Знову спрощуємо наш арифметичний вираз: :)
printf("%six\012\0", 'r'+"gun"-0x71);


На кінці рядка "%six\012\0” бачимо символ '\0' - це "кінець рядка".
Оскільки там у нас перед ним стоїть символ "перехід на новий рядок" - '\012',
то ми можемо символ "кінець рядка" викинути, а представлений у шістнадцятковому
коді "перехід на новий рядок" представити у зручному для людини вигляді - '\n'.
Спрощуємо вираз ще раз:
printf("%six\n", 'r'+"gun"-0x71);

Символ 'r' у шістнадцятковому коді представлений як “0x72”, тож, для показовості прикладу перепишемо його:
printf("%six\n", 0x72+"gun"-0x71);

Від 0x72 відняти 0x71 буде 1. Спростімо вираз іще раз:
printf("%six\n", "gun"+1);

Таким чином "gun"+1 - це просто указка на рядок, що починається з літери "u". Спрощуємо:
printf("%six\n", "un");

На завершення маємо форматний символ "%s", що заміняє будь яку символьну змінну в аргументах функції “printf()”.
У нашому випадку це “un”, а рядок "ix" лише жорстко дописується до відформатованих за допомогою "%s" символів.

Востаннє спрощуємо:
printf("unix\n");

Відповідь: "unix". :)

---

Date: 2011-01-23 04:32 pm (UTC)
From: [identity profile] pencioner.livejournal.com
>> За такі збочення, на мою думку, у практичному програмуванні треба бити до памороків

Ну, дивлячись що за команда і т.п. Якщо, як це зараз у 80% випадків буває, команда молодих лайнокодерів, котрі наприклад навіть не знають двійкової/побітової арифметики і власне думати не вміють, тільки код строчити а потім карячитись відловлюючи баги, то мабуть того умніка що таке написав треба побити щоб більше такого не писав, та поставити старшим на іншими.

А якщо всі люди нормальні, то таке писати можна. З коротким коментарем. Наприклад, замість

elem = array1[array2[array3[array4[index]]]]

мені було б приємніше побачити

// a[i] == i[a] == *(a+i) // ask Kernighan if not sure
elem = index[array4][array3][array2][array1]

та й вкладених брекетів менше - легше читається :)

заодно той хто цього не знав набуде цієї інформації

Date: 2011-01-23 06:03 pm (UTC)
From: [identity profile] je-suis-la-vie.livejournal.com
>"elem = index[array4][array3][array2][array1]"

Так-так, цей вираз має практичний і дужепотужний зміст. Бувають винятки. :))) Дякую, колего. :)))

Profile

je_suis_la_vie: (Default)
je_suis_la_vie

April 2017

S M T W T F S
      1
2345678
9101112131415
16 171819202122
23242526272829
30      

Style Credit

Expand Cut Tags

No cut tags
Page generated May. 26th, 2017 03:00 pm
Powered by Dreamwidth Studios