typedef int (*pf)(int, int);
char c[] = {85,-119,-27,-117,69,12,3,69,8,93,-61,-112};
pf sum = (pf)c; //reinterpret_cast отказывается, поэтому так.
cout << sum(2,3); //Вывод 5.
* This source code was highlighted with Source Code Highlighter.
Теперь sum - функция сложения, являющаяся аналогом этой:int sum(int a, int b){return a+b;}
Сначала я написал нормальную функцию sum, затем байт за байтом просмотрел ее содержимое в памяти. К сожалению sizeof к функциям неприменим, поэтому я, после sum, определил еще одну функцию, и предположил, что в памяти они тоже рядом. Их адреса различались на 12 байт.
UPD: Одной строкой:
cout << ((int (*)(int, int))"\x55\x89\xE5\x8B\x45\x0C\x03\x45\x08\x5D\xC3\x90")(2,3);
То есть инструкция "return a+b" в памяти хранится как набор байт? И мы кладем этот набор байт в память, создаем функцию, которая будет указывать на начало этого набора? И значит при ее вызове будет исполнятся код "return a+b". Я правильно понял?
ОтветитьУдалитьИ так можно сделать с любой функцией?
Ага, все функции хранятся в памяти как набор байт (как и данные). В примере мы искусственно поместили эти байты в память и сказали (с помощью приведения), что это именно функция.
ОтветитьУдалитьЯ писал на Хабре об этом, можешь почитать комментарии, для меня они оказались полезны.
http://habrahabr.ru/blogs/cpp/71234/
Спасибо, прочитал комменты на Хабре. Многие пишут фразы "За такое нужно руки отрывать". По моему это все понты. Это же просто демонстрация, никто не говорит, что так нужно писать коммерческие продукты. Ты молодец, что пытаешься во всем разобраться.
ОтветитьУдалитьСпасибо! Конечно так делать не нужно, но это важно для понимания.
ОтветитьУдалить