Издательский дом ООО "Гейм Лэнд"ЖУРНАЛ ХАКЕР #90, ИЮНЬ 2006 г.

Трюки от Криса

Крис Касперски

Хакер, номер #090, стр. 090-128-1


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

Хак №1 – функции под вопросом

Начнем с классики (см. листинг 1). На вопрос: «Что этот код делает?» большинство прикладных программистов убежденно отвечают: "Не компилируется". Те же из них, кто все-таки не поленится проверить и откомпилировать, едут крышей и остаток дня проводят в размышлениях: как такое вообще может работать?

j = (flag?sin:cos)(x);

Хороший тест на значение языка. Что данный код делает, понятно и без подсказки, достаточно открыть описание оператора "?", но объяснить, как он это делает, может только гуру.

При использовании имени функции в качестве выражения, компилятор возвращает на нее указатель. Таким образом, в зависимости от значения flag'а, будет выбран либо тот, либо иной указатель, заключенный, согласно правилам языка, в круглые скобки и ожидающий аргументов, в роли которых в данном случае выступает (x).

А теперь попробуй переписать этот хак на классический манер и сравни размер программы и откомпилированного кода.

Хак №2 – обмен значений двух переменных

Вопрос: сколько времени потребуется рядовому программисту, чтобы понять, что происходит с переменными x и y?

x ^= y ^= x ^=y;

Давай разобьем это выражение на три: "x ^= y; y ^= x; x ^= y;", для наглядности записав их так:

1) x = x XOR y;

2) y = y XOR x;

3) x = x XOR y;

А это уже чистая математика получается! Повторное наложение И, исключающего ИЛИ, независимо от порядка аргументов, как известно, дает исходный результат, но в строках 1 и 2 аргументы меняются местами, следовательно, после выполнения шага 2 в переменной y окажется x, а сам x будет содержать "смесь" (x XOR y), из которой на шаге 3 "изымается" прежний x и остается чистый y. Короче, происходит обмен значений двух переменных, без привлечения третьей.

Красиво? Красиво! Но, увы, по скорости и объему машинного кода сильно проигрывает стандартному "tmp = x; x = y; y = tmp;", поэтому пользоваться данным хаком не рекомендуется.

Хак №3 – забытая запятая

Изобилие фигурных скобок сильно раздражает, и возникает естественное стремление записать весь statement одной строкой. Рассмотрим типичный фрагмент кода, написанный "правильным" программистом:

if (n > 1)

{

printf("%d\n", x); n=0; a++;

}

А вот тот же самый код, написанный хакером. Как говорится, сравни и найди различия:

if (n >1) printf("%d\n", x), n = 0, a++;

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

Постоянно разделяя операторы знаком точки с запятой, большинство программистов почему-то забывают об обыкновенной запятой, используемой для разделяющих выражений, но в си практически все что угодно может быть выражением!!!

Содержание  Вперед на стр. 090-128-2
Hosted by uCoz