Убедил. Нужен WinMain (для subsystem:windows). Этот чертов crt уже начинает нервировать О typedef: первоначально я его использовал при вызове sprintf из ntdll, и почему-то был уверен, что в ntdll все функции stdcall. Оказалось нет. Ну и по наследству typedef достался msvcrt.dll И тогда ещё один вопрос по sprintf: Код (Text): void foo (char *dest, char *fmt, ...){ //как передать входные параметры в sprintf? sprintf (dest, fmt, ?????????); } Если бы sprintf принимал третьим параметром va_list, я бы ему сформировал и отдал бы его(как в случае с wvsprintf).. Но он хочет набор аргументов. va_arg я тоже использовать не могу, т.к. va_arg'у нужны параметры одного типа, если я правильно понимаю. Т.е. либо все int, либо все char* и т.д. А у меня параметры могут быть разного типа. Можно попробовать через asm оттянуть стек вниз, скопировать входные параметры к новой вершине стека+4, в вершину положить адрес возврата и далее jmp на sprintf. Но это как-то слишком экстравагантно. Должен быть способ без таких выкрутасов.
Думаю, что по-другому никак. Тут даже дело не в типах параметров (кажется, они могут быть любого типа), а в том, что их надо как-то передать, т.е. вызов sprintf должен содержать вполне определенное число параметров. Поэтому придется делать что-то в этом роде: Код (Text): push param1 push param2 ... push paramN push fmt call sprintf add esp, N
cresta Т.е. у foo и sprintf одинаковые аргументы? Тогда почему просто jmp sprintf не сделать? [+] Или помимо вызова sprintf в foo происходят еще какие-то действия? Тогда IMHO это неосуществимо, т.к. за стеком постоянно следить надо - что и когда туда положли и забрали.
Код (Text): #define lsys_log_error(level, ...) \ if (cfg->debug_level >= level) \ lsys_log_error_core(level, __VA_ARGS__) #define lsys_log_debug(...) \ lsys_log_error_core(LSYS_LOG_DEBUG, __VA_ARGS__)
Код (Text): Variadic Macros Variadic macros are function-like macros that contain a variable number of arguments. Remarks To use variadic macros, the ellipsis may be specified as the final formal argument in a macro definition, and the replacement identifier __VA_ARGS__ may be used in the definition to insert the extra arguments. __VA_ARGS__ is replaced by all of the arguments that match the ellipsis, including commas between them. The C Standard specifies that at least one argument must be passed to the ellipsis, to ensure that the macro does not resolve to an expression with a trailing comma. The Visual C++ implementation will suppress a trailing comma if no arguments are passed to the ellipsis. Example Copy Code // variadic_macros.cpp #include <stdio.h> #define EMPTY #define CHECK1(x, ...) if (!(x)) { printf(__VA_ARGS__); } #define CHECK2(x, ...) if ((x)) { printf(__VA_ARGS__); } #define CHECK3(...) { printf(__VA_ARGS__); } #define MACRO(s, ...) printf(s, __VA_ARGS__) int main() { CHECK1(0, "here %s %s %s", "are", "some", "varargs1(1)\n"); CHECK1(1, "here %s %s %s", "are", "some", "varargs1(2)\n"); // won't print CHECK2(0, "here %s %s %s", "are", "some", "varargs2(3)\n"); // won't print CHECK2(1, "here %s %s %s", "are", "some", "varargs2(4)\n"); // always invokes printf in the macro CHECK3("here %s %s %s", "are", "some", "varargs3(5)\n"); MACRO("hello, world\n"); // MACRO("error\n", EMPTY); would cause C2059 } Output here are some varargs1(1) here are some varargs2(4) here are some varargs3(5) hello, world Кажется, это только в макросах применимо.
IceStudent _vscprintf принимает va_list _вторым_ аргуметом, но ход мыслей правилен. cresta Если бы sprintf принимал третьим параметром va_list Есть такая в crt - vsprintf (ANSI C compatibility). Использовать так Код (Text): void foo (char *dest, char *fmt, ...){ va_list ap; va_start(ap, fmt); // sprintf (dest, fmt, ?????????); vsprintf(dest, fmt, ap); va_end(ap); } ps ты заботишся о размере буфера для dest?
KeSqueer За стеком следить не так и сложно. Просто хочется готового решения q_q Проглядел vsprintf... Попробовал кучу других XXXprintf в поисках принимающей va_list и поддерживающей спецификатор %f, а именно vsprintf выпала из поля зрения. Возвращаясь к crt: может ли msvcrt полноценно заменить libcmt? Сделал так: Код (Text): #pragma comment(linker, "/nodefaultlib:LIBC") #pragma comment(linker, "/nodefaultlib:LIBCMT /NODEFAULTLIB:OLDNAMES") #pragma comment(linker, "/defaultlib:MSVCRT") пока ничего криминального не вижу, программа вроде работает, но может есть какие-то подводные камни? Кроме необходимости наличия msvcrt.dll ?
Я уже говорил выше о идентичности. То есть, для тебя, как для разработчика, разица только одна: в типе линковки (динамической или статической). Со всеми вытекающими последствиями (скорость вызовов, размер программы, etc.).