Pull to refresh

Comments 38

доведем задачу до абсурда
По-моему у вас получилось. Почему 0x17? Из-за 0x0b?
Ничем специальным число не обусловлено. Просто генератор выдал именно 0x17 и дальше пошло-поехало.
Блин, уже на втором примере сломал мозг…
Хочу поставить 0х17 лайков. Но с пояснениями статья была бы намного интереснее и полезнее.

Второй пример сильно попахивает неопределённым поведением и индексацией случайных адресов памяти. Или я неправ?
Нет, UB нет ни в одном из примеров.
Я обдумывал идею добавить разборы, но они сделали бы статью существенно скучнее. В итоге решил оставить без пояснений, благо комментарии позволяют обсудить конкретные места.

Нет. (!true)["true"] — это то же самое что "true"[0], т.е. символ 't'. Со второй частью аналогично.

Вроде как ptr[n] == n[ptr], то есть это выражение эквивалентно ('t' -'F') >> 1 => 0x2e >> 1 => 0x17
Здесь всё в порядке: x[y] раскрывается в *(x + y).
Да, дошло через 5 минут модификаций кода в ideone, чтоб понять, что же он делает. А комментарий ни добавить, ни отредактировать уже не мог. В общем, надо сначала подумать, а потом уже в комментариях спрашивать :)

Только насчёт x + y не согласен, потому что здесь это явно раскрылось в y+x. Арифметика указателей разве коммутативна?

Коммутативность не имеет никакого отношения к "арифметике указателей". Коммутативен встроенный бинарный оператор + и коммутативен абсолютно всегда, безусловно и во всех контекстах.

Я о том, что совершенно не очевидно, что int + char* — такая же валидная операция, как char* + int. Более того: возможно, даже, имело бы смысл сделать первый вариант синтаксической ошибкой.

Я не вижу никакой опасности в такой коммутативности. А запрещать чисто ради запрещения в С не принято.

Простите, но там в начале разве должна быть O (буква) или все же 0 (цифра)?


int Ox01 = ~-~-~-~-~-~-~-~-~-' ';
Названия переменных же нельзя начинать с цифры. Вот и выкрутились
Точно, не заметил что это название переменной.
Есть еще сильно подгонный вариант (по сути будет работать только в вашем примере на Ideone, и может еще на других 64 битных машинах с linux, gcc 6.3 и использующих ту же версию libc) — в глобальных переменных обьявить extern «C» void _start(); (в случае чистого C — просто extern) а непосредственно в main int Ox18 = ~((char*)_start)[142];
В некоторых промежуточных версиях у нас были подобные варианты, например, через отрицательные индексы массивов, но в итоге, от них решили отказаться, поскольку они очень ненадежные.
Вообще говоря общая идея — это использовать оп код вызова call x86 ассемблера, я пока думаю как это можно сделать 100% предсказуемым образом.
P.S сори, промахнулся веткой :(
Нумерация OxZZ не с нуля — вся статья на выброс.
Ну хоть кто-то заметил, а я уже начал терять веру в людей.
Разве это не было сделано, что бы последняя переменная было с номером 0x17?
Примерно так. Но даже если бы отсчет шел с Ox00 по Ox16 общее количество в 0x17 все равно было бы очевидно.

Во-первых, ваши решения написаны не на С, а на GCC, да и те платформеннозависимы. Такие задачи интереснее решать именно на стандартном С. Ваши решения в большинстве своем к С относятся мало или вообще никак.


Во-вторых, ideone в профессиональных кругах не считается уважаемым или убедительным ресурсом, особенно в вопросах С, поэтому заявления вида "для сомневающихся — ссылка на ideone" никаких сомнений не развеивают, а могут вызвать лишь facepalm.

Запросто!


На "во-первых" аргументы очевидны: большинство вариантов завязаны на свойство платфоременно-зависимого character set. Вот и все. К тому же фактически способов что-то сделать у вас от силы три. И один из них — применение * к строковому литералу — раздут в огромное число вариантов. Зачем было делать искусственное и скучное раздувание этих способов в такое количество уныло повторяющихся вариантов — не ясно. Это же сразу бросается в глаза.


Найти остроумные решения, которые бы работали на настоящем стандартном С — вот это действительно интересная задача, потому что в ней заключается challenge. А ваши чисто косметические выверты на фактически готовеньком результате (т.е. на конкретных значениях character constants) — примитивная пустышка/профанация для студенток-первокурсниц.


На "во-вторых" аргументы тоже несложны: хорошо известно, что ideone занимается наглой пост-фильтрацией диагностических сообщений компилятора. Не видя стандартных диагностических сообщений компилятора рядовой пользователь не сможет судить о корректности кода. Ваш код грубо ошибочен, но тем не менее проглатывается ideone — вескость этого аргумента переоценить невозможно.


Например, для использования true и false обязательно требуется включение <stdbool.h>. Для использования compl и xor обязательно требуется включение <iso646.h>. У вас же ideone в режиме С (!) проглотил это все даже не поперхнувшись. Именно по таким причинам в темах по языку С не принято оскорблять присутствующих ссылками на потешные глюкала типа ideone. Возмите в привычку пользоваться общепризнанными стандартами типа coliru. Какой бы вы ресурс не использовали, контроль над командной строкой компилятора — обязателен.


P.S. Ой, только что обратил внимание! Вы вообще в С++ это все компилировали! Так зачем же вы нам тогда баки забиваете какими то сказками про "практику программирования на C"?

А я все думал, когда же вы заметите про c++.
Я себе ограничений в «чистый си, где даже даже в ASCII нельзя быть уверенным» не ставил.
Произошло ровно то, что написано в статье — мой код оскорбил практики программирования на си.

На С++ все даже хуже, ибо в С++ символьная константа имеет тип char, а не int. И это значит, что в С++ все ваши символьные константы будет подвергаться integral promotions, которые, в зависимости от платформы, могут превратить ее в int или в unsigned int. Вариант с unsigned int — целый ящик Пандоры самостоятельных проблем. (Хотя аналогичные проблемы с integral promotions присутствуют в этом коде и с точки зрения С).

Тем не менее, используемый character set не является чем-то уникальным для GCC, так что ваше утверждение «решения написаны на GCC» все еще странное.

Это не принципиально. Завязка на character set в решении таких задач — это совершенно неинтересный читинг. А тут еще 90% приведенных "решений" — унылое повторение снова, снова и снова одного и того же приема с *"строка", к тому же завязанного на character set.

UFO just landed and posted this here
На картинке для кликбайта написано 0x17 а в решениях совсем другое
int Ox07 = '.'>>!false;
int Ox17 = 010-001+010+010;
какая то даже не пятничная статья
Кстати, мы ищем Питон-разработчика, который умеет программировать понятнее чем я. Присоединяйтесь!
404
видимо, URL'ы получаются не лучше кода на Python
Довольно необычная претензия к статье старше двух лет при очевидной временности ссылки. Разработчиков на Питоне не настолько мало, чтобы вакансия висела годами.
Но правда ваша, ссылку стоило удалить, как она потеряла актуальность. Удалил сейчас.
Only those users with full accounts are able to leave comments. Log in, please.