Всех приветствую, вопрос относится к Си без плюсов. вопрос относится к каллбекам которые принимают указатели void* есть у нас например модуль сторонний который для выполнения некоторых действий позволяет регистрировать каллбеки пусть сигнатура их такова Код (Text): void callback_func(void*, void*); так вот когда я пишу свою функцию каллбека чтобы передать ее адрес в дальнейшем я могу написать так Код (Text): void callback_func(void *it1, void *it2) { char *pFirst = it1; char *pSecond = it2; } например этот модуль в аргументах каллбека передает указатели на строки но в отладчике MSVC внутри каллбека так просто не посмотреть значение параметров приходится или заводить переменные нужного типа или делать как то так Код (Text): ///////watch////// //(char*)it1,100// //(char*)it2,100// ////////////////// но намного удобней сразу написать Код (Text): void callback_func(char *it1, char *it2) { } вот реальный пример сигнатура этого каллбека по идее такая Код (Text): int comp(const void *it1, const void *it2); но определяю я ее по другому Код (Text): int comp(const gchar *it1, const gchar *it2) { int r; r = strcmp(it1, it2); return r == 1 ? -1 : r == -1 ? 1 : 0; } здесь особой нужды в параметрах нужного типа нет но это только пример при вызове каллбека в отладчике сразу видно значения параметров компиляция тоже без предупреждений проходит да и внутри каллбека заводить новые переменные нужного типа а потом присваивать им аргументы не надо или как то извращатся в окне watch вопрос чем это может вылезти боком в будущем и/или на других компиляторах платформах есть мысли что все приведения в подобных случаях в Си коде для того чтоб код без предупреждений и Си++ компилятором собирался но если совместимость с Си++ не планируется можно ли так делать чем это плохо/чем может вылезти боком в будущем ?
osox, вы умеете объяснять коротко и понятно. проблема будет в том, что вот такой код компилиться не будет: Код (Text): typedef int func_t(void*, void*); int func(char* s1, char* s2) { return 0; } int main() { func_t *p_func; p_func = func; } при присваивании придётся явно преобразовывать тип. думаю, будет лучше, если во всех колбеках список аргументов будет тот, который заявлен. чтобы посмотреть, есть замечательные клавиши Ctrl+Alt+Q. или заведите в начале функции переменные типа char*.
в том то и дело что собиратся ваш пример будет без предупреждений даже на /W4 самом высоком уровне предупреждений проверил и на MSVC 2010 и на LCC
Ну на всякий случай, для совместимости с с++ можете сделать типа так: Код (Text): typedef void (*callback_t)(void*, void*); void i_get_callback(int, callback_t); void my_callback(const char*, const char*); ... i_get_callback(0, (callback_t)my_callback); а вообще ни к чему не приведет, в си, типы демократичней автоматом кастуются =)
Ну, знаете, даже такой код компилится, хотя и с предупреждением. Тем не менее, стек валится. Код (Text): typedef int __stdcall func_t(void*, void*); int __stdcall func(char* s1) { return 0; } int main() { func_t *p_func; p_func = func; (*p_func)(0, 0); }
был бы __cdecl все прошло бы гладко а так можно самому подкорректировать Код (Text): typedef int __stdcall func_t(void*, void*); int __stdcall func(char* s1) { return 0; } int main() { func_t *p_func; p_func = func; __asm { push 0; push 0; call p_func; add esp, 4; } }
osox, ну-ну. корректируйте. что касается формата вызовов - он нигде не определён. возьмите какой-нибудь BorlandC и всё свалится. Сам сталкивался: один и тот-же __fastcall VC и BC воспринимают по-разному. Какой формат вызова стоит по дефолту - х.з. Рассчитывать на это, а тем более, корректировать стек - это такая ж... Мало того, что кастыль, так ещё непортабельно. Делайте как вам посоветовали в самом начале: Код (Text): typedef int __stdcall func_t(void*, void*); int __stdcall func(void* p1, void *p2) { char *s1 = (char*)p1; char *s2 = (char*)p2; return 0; } int main() { func_t *p_func; p_func = func; (*p_func)(0, 0); } за лишние переменные не бойтесь - компилятор от них избавится при оптимизации.
maksim_ это все аргументы ? я не спрашивал как мне делать я спрашивал почему и какие последствия могут быть вы же привели пример использующий __stdcall и при этом явно нарушающий конвенцию вызова что не имеет никакого отношения к моему вопросу он был совсем в другом или вы хотели показать что не все что компилится работает ? это я и без вас знаю надо по существу отвечать или не отвечать вовсе если есть что то по моему вопросу и по существу пишите
osox. Больно надо. Не хотите слышать советов - не задавайте вопросы. Тем более так: "Знаеш ? Подскажи !", что соответствует правилам форума. Удачи.