Комментарии 47
Действительно ненормальное программирование. Не позавидую тому, кому прийдется сопровождать после Вас такой код. А вообще идея интересная.
Никому не нужно будет сопровождать, так как проект личный и делался в целях самообразования и поиска нестандартных решений. Так же хотелось прощупать возможности кимпилеров по оптимизации.
Реализация понравилась. А вот сама идея, не очень. Понятно, что где то в коде будет кусок кода парсящий какую-нибудь dll-ку на предмет выдергивания имен из IMAGE_IMPORT_DESCRIPTOR с последующей передачей этих строк в ваш хеш. А перед всем этим действом LoadLibrayA (some_name). Так что bp kernel32!LoadLibraryA ".printf «from %x library = <%ma>\n», poi(esp), poi(esp+4);g" Очень быстро выводит на след. Поэтому на всякий случай скажу вот, что добавьте сюда самостоятельный парсинг PE заголовка и когда вытащите адрес интересующей вас функции делайте jmp не на нее, а скажем на address_of_function + 5. Вот это уже будет веселее. Но все равно понравилось.
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
С++ не имеет встроенных средств написания чисел в двоичном виде.
а
int myBinaryNumber = 0b0110110;
уже отменили? Или я что-то неправильно помню?Неправильно помните )
0b0110110 — это в новой Java (JDK 7).
А это тогда как объясните?
#include <iostream>
using namespace std;
int main()
{
int num = 0b0010010;
cout << num << endl;
return 0;
}
beaver@gentoo /home/beaver/1 $ g++ 1.cpp -o 1
beaver@gentoo /home/beaver/1 $ ./1
18
НЛО прилетело и опубликовало эту надпись здесь
GNU C provides several language features not found in ISO standard C… gcc.gnu.org/onlinedocs/gcc/Binary-constants.html
В свое время написал такую штуку для двоичных чисел: paste.org/pastebin/view/28312
Юзается просто: BINARY(11010001)
Юзается просто: BINARY(11010001)
hash_text очень странный, какой в нем смысл? Если функция runtime. Почему нельзя было использовать тернарный оператор и enum или static const unsigned int переменную, например как сделано в code_text для count. Тогда будет compile-time. А для двоичных чисел просто изврат какой-то. Вот реальный рабочий пример, без извратов и с минимумом кода.
template
struct binary
{
static const int value = (N % 10) + 2 * binary< N / 10 >::value;
};
template
struct binary
{
static const int value = 0;
};
использование
binary::value;
и в результате полнейший compile-time.
На будущее я бы посоветовал покопать в сторону мета-программирования на сях.
Почитать
Джеф Элджер C++ for Real Programmers (есть на русском)
Андреq Александреску Modern C++ Design (есть на русском)
David Abrahams and Aleksey Gurtovoy, C++ Template Metaprogramming: Concepts, Tools, and Techniques from Boost and Beyond (на русском не видел).
А уже затем заниматься ненормальным программированием.
template
struct binary
{
static const int value = (N % 10) + 2 * binary< N / 10 >::value;
};
template
struct binary
{
static const int value = 0;
};
использование
binary::value;
и в результате полнейший compile-time.
На будущее я бы посоветовал покопать в сторону мета-программирования на сях.
Почитать
Джеф Элджер C++ for Real Programmers (есть на русском)
Андреq Александреску Modern C++ Design (есть на русском)
David Abrahams and Aleksey Gurtovoy, C++ Template Metaprogramming: Concepts, Tools, and Techniques from Boost and Beyond (на русском не видел).
А уже затем заниматься ненормальным программированием.
Блин, вырезались знаки больше-меньше, код
template<int N>
struct binary
{
static const int value = (N % 10) + 2 * binary<N / 10>::value;
};
template<>
struct binary<0>
{
static const int value = 0;
};
использовать
binary<11101111>::value
template<int N>
struct binary
{
static const int value = (N % 10) + 2 * binary<N / 10>::value;
};
template<>
struct binary<0>
{
static const int value = 0;
};
использовать
binary<11101111>::value
binary<00101001> работать не будет, т.к. восьмеричное. Но идея, конечно, лучше чем куча ифов.
Такое тоже имеет право на жизнь и я об этом знаю, вопрос в том сколько разрядов поместится? В вашем примере малавато будет, в моем примере намного больше, хотя и выглядит похуже, но цель была не в этом
Ну да, минус только в разрядах, но для большинства задач хватает небольшого кол-ва, можно использовать 64 битный тип, будет побольше разрядов. Но в данном примере полный compile-time, а для run-time можно просто строку использовать.
На худой конец можно было хотябы избавится от run-time, а синтаксис оставить подобным, что-то типа.
Что-то типа для одного байта, расширять можно до бесконечности
#include <iostream>
// Основной тип для вычисления, здесь пробегаем рекурсивно число.
template<
int c01 = -1, int c02 = -1, int c03 = -1, int c04 = -1,
int c05 = -1, int c06 = -1, int c07 = -1, int c08 = -1
>
struct bin_to_dec
{
enum {value = bin_to_dec<-1, c01, c02, c03, c04, c05, c06, c07>::value << 1 | c08};
};
// Тип для ротации вправо, в случае, если указаны не все биты.
template<
int c01, int c02, int c03, int c04, int c05, int c06, int c07
>
struct bin_to_dec<c01, c02, c03, c04, c05, c06, c07, -1>
{
enum {value = bin_to_dec<-1, c01, c02, c03, c04, c05, c06, c07>::value};
};
// тип для завершения вычислений, для завершения рекурсии первого типа
template<>
struct bin_to_dec<-1, -1, -1, -1, -1, -1, -1, -1>
{
enum {value = 0};
};
int main(int argc, char *argv[])
{
std::cout << bin_to_dec<1,0,1>::value << std::endl;
std::cout << bin_to_dec<0,1,1,0,0,1,0,1>::value << std::endl;
return 0;
}
В результате мы получили compile-time, нужно только подумать.
Что-то типа для одного байта, расширять можно до бесконечности
#include <iostream>
// Основной тип для вычисления, здесь пробегаем рекурсивно число.
template<
int c01 = -1, int c02 = -1, int c03 = -1, int c04 = -1,
int c05 = -1, int c06 = -1, int c07 = -1, int c08 = -1
>
struct bin_to_dec
{
enum {value = bin_to_dec<-1, c01, c02, c03, c04, c05, c06, c07>::value << 1 | c08};
};
// Тип для ротации вправо, в случае, если указаны не все биты.
template<
int c01, int c02, int c03, int c04, int c05, int c06, int c07
>
struct bin_to_dec<c01, c02, c03, c04, c05, c06, c07, -1>
{
enum {value = bin_to_dec<-1, c01, c02, c03, c04, c05, c06, c07>::value};
};
// тип для завершения вычислений, для завершения рекурсии первого типа
template<>
struct bin_to_dec<-1, -1, -1, -1, -1, -1, -1, -1>
{
enum {value = 0};
};
int main(int argc, char *argv[])
{
std::cout << bin_to_dec<1,0,1>::value << std::endl;
std::cout << bin_to_dec<0,1,1,0,0,1,0,1>::value << std::endl;
return 0;
}
В результате мы получили compile-time, нужно только подумать.
миль пардон, но относительно бинарных чисел это не изврат. Чисто технически понимание дизасма в первом случае займет чуть больше времени, чем какой-нибудь классический алгоритм назначение, которого понятно сразу.
Ну здесь требуется понимание работы шаблонов, а это думаю не сложно, простейший рекурсивный шаблон. Если же пользоваться шаблонами и не знать как они работают, это не есть хорошо. Да и существуют комментарии, к хитрому коду пишу всегда, если наоборот не требуется запутать.
Мы судим с несколько разных точек зрения. Вы, судите о том на сколько удачно поставленная задача решается инструментарием языка C++. Я сужу о том насколько
эффективно решена задача, а решена она прямо скажем слабенько. Но судя по всему человек этим занимался явно первый раз в жизни. Так что на мой взгляд все не так уж и плохо. А вот относительно темплейтов соглашусь. На самом деле — это просто впустую потраченное автором время. На уровне дизасма никаких темплейтов попросту не существует.
эффективно решена задача, а решена она прямо скажем слабенько. Но судя по всему человек этим занимался явно первый раз в жизни. Так что на мой взгляд все не так уж и плохо. А вот относительно темплейтов соглашусь. На самом деле — это просто впустую потраченное автором время. На уровне дизасма никаких темплейтов попросту не существует.
Ну про первый раз с шаблонами вы явно загнули, я с ними работаю с момента их появления на С++. А насчет дизасма, вы не совсем поняли, цель была в формировании хэшей во время компиляции, естественно никаких шаблонов в результирующем exe не будет, будут только хеши для сравнения и больше ничего не требовалось. Также и со строками, будет только кодированный текст сформированный самим компилятором.
нет, ведущие нолики не указывать и будет работать.
Думаю, что с появлением C++0x ваш можно будет реализовать более элегантно. Я бы советовал посмотреть в сторону variadic templates и user-defined literals. Вот пример из статьи C++0x в википедии:
template<char...> OutputType operator "" _suffix();
OutputType some_variable = 1234_suffix; // operator "" _suffix<'1', '2', '3', '4'>()
Добавляю в избранное только из-за комментов, в том числе будущих.
Добавлю еще и я свой вариант для вычисления в compile-time двоичных литералов:
template <int N>
int parse_binary(const char *s)
{
int ret = 0;
for (size_t i = 0; i < N; ++i) {
ret = (ret << 1) + (s[i] == '0'? 0 : 1);
}
return ret;
}
template <int N>
int parse_binary(const char (&s)[N])
{
return parse_binary<N-1>(static_cast<const char *>(s));
}
#define BIN(b) parse_binary(#b)
int main(int argc, char* argv[])
{
return BIN(11000000); // mov eax, 192
}
Простите, а где здесь compile-time? Я так понимаю compilte-time тут будет только если этого захочет оптимизатор, а иначе будет run-time? Или я ошибаюсь?
Все зависит от компилятора и длины исходного кода, но в большинстве случаев всегда будет compile-time, но если код слишком большой (как в примере кодирования строк, а у меня в реальном проекте он раза в два больше), то иногда надо увеличить в параметрах длину инлайн функций, как мне пришлось сделать в gcc, а OpenWatcom все чудесно проглотил без проблем
Да, от оптимизации зависит.
Но, как уже рядом ответили, в большинстве случаев такая оптимизация срабатывает.
Но, как уже рядом ответили, в большинстве случаев такая оптимизация срабатывает.
Простите, но зачем шаблоны, когда гораздо проще и красивее было бы сделать то же самое макросом?
Макросами не будет красиво и наврядли с помощью них такое возможно сделать. Да и макросы являются наследием С, и для С++ с его шаблонами их не рекомендуют применять. Хотя я может чего-то не знаю, если вы считаете что макросами можно такое сделать, то приведите пример.
Во-первых, Вы недооцениваете мощь макросов, в них это реализуемо :) Реализовывать именно этот алгоритм лень из-за того, что получится длинновото, но получится что-то в духе:
где
Во-вторых, если инструмент есть, если он работает, почему его нужно сознательно игнорировать?
#define HASH(s) s[0]? ... : ...
где
...
будут достаточно длинными :)Во-вторых, если инструмент есть, если он работает, почему его нужно сознательно игнорировать?
Дело в том что наврядли с помощью макросов можно сделать такие вычисления во время компиляции (макросы это ведь подстановки, а шаблоны это уже вычисления). Интересно как можно с помощью макросов определить конец строки? Причем так чтобы дальше не было вычислений.
Да Вы что? Компилятор давно разучился вычислять константы во время компиляции? o_O
В общем, не читайте тех газет, которые говорят, что макросы — фуфло. Макросы — сила, пусть они и послабее шаблонов будут. Я вот когда мне не хватало возможностей препроцессора cpp (cpp != c++, это название самой программы-препроцессора C), подключил m4, который, кстати, является полноценным языком программирования.
Я не считаю макросы фуфлом, просто они, как вы сказали, слабее шаблонов, я еще добавлю — намного слабее. Да и выглядят макросы не совсем хорошо по сравнением с шаблонами. Сейчас попробовал с помощью макросов сделать вычисление хэша, не получилось, мало того, код выглядит намного ужасней и непонятней. Попробуйте сами хотя бы для 4-х символов и при этом учтите, что может передаваться строка меньшего размера.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Формирование данных с помощью шаблонов С++