CreateThread中的转换错误

CreateThread中的转换错误,c,visual-studio,winapi,C,Visual Studio,Winapi,当我尝试使用CreateThread函数时,我有一个奇怪的bug。这是我的密码: HANDLE threads[3]; //threads[0] is printer, threads[1] is receiver, [2] is serverconn DWORD printer_id, receiver_id, serverconn_id; if( ((threads [0] = CreateThread(NULL, 0, pr

当我尝试使用CreateThread函数时,我有一个奇怪的bug。这是我的密码:

HANDLE threads[3];  //threads[0] is printer, threads[1] is receiver, [2] is serverconn
    DWORD  printer_id,  receiver_id, serverconn_id;
    if(
                      ((threads [0] = CreateThread(NULL, 0, printer_thread,    (LPVOID) thread_args, 0, &printer_id)) == NULL) ||
        ((recv_thread = threads [1] = CreateThread(NULL, 0, receiver_thread,   (LPVOID) thread_args, 0, &receiver_id)) == NULL) ||
                      ((threads [2] = CreateThread(NULL, 0, serverconn_thread, (LPVOID) thread_args, 0, &serverconn_id)) == NULL)
    )
    {
        IO_print_line("Initialization error");
        return FALSE;
    }
打印机线程、接收器线程和服务器连接线程是定义如下的函数:

if(
                      ((threads [0] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) &printer_thread,    (LPVOID) thread_args, 0, &printer_id)) == NULL) ||
        ((recv_thread = threads [1] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) &receiver_thread,   (LPVOID) thread_args, 0, &receiver_id)) == NULL) ||
                      ((threads [2] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) &serverconn_thread, (LPVOID) thread_args, 0, &serverconn_id)) == NULL)
    )
int serverconn_threadLPVOID参数

Visual Studio编译器给了我以下错误:

Error   C2440   'function': cannot convert from 'int (__cdecl *)(LPVOID)' to 'LPTHREAD_START_ROUTINE'
我真的不明白,因为我认为我已经做到了

不,将线程函数的返回类型更改为DWORD不会解决任何问题,错误只会更改为:

Error   C2440   'function': cannot convert from 'DWORD (__cdecl *)(LPVOID)' to 'LPTHREAD_START_ROUTINE'
奇怪的是如果我这样改变它:

if(
                      ((threads [0] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) &printer_thread,    (LPVOID) thread_args, 0, &printer_id)) == NULL) ||
        ((recv_thread = threads [1] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) &receiver_thread,   (LPVOID) thread_args, 0, &receiver_id)) == NULL) ||
                      ((threads [2] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) &serverconn_thread, (LPVOID) thread_args, 0, &serverconn_id)) == NULL)
    )
对于强制强制转换,编译器是可以的,但我不认为以这种方式强制它是一个好主意。如何修复此问题?

在声明线程函数时,您没有遵循

您最初的声明使用int作为返回值,而_cdecl隐式地作为调用约定。将返回值更改为DWORD时,没有更改调用约定

但是,以下内容清楚地表明了正确的声明:

DWORD WINAPI ThreadProc( _In_ LPVOID lpParameter ); 但是,由于CreateThread将LPTHREAD_START_例程作为输入,声明为DWORD WINAPI*LPVOID请参见winbase.h中的实际声明,因此您应该声明您的函数以匹配:

DWORD WINAPI printer_thread(LPVOID args);
DWORD WINAPI receiver_thread(LPVOID args);
DWORD WINAPI serverconn_thread(LPVOID args);

那么,为什么官方的微软示例使用DWORD WINAPI MyThreadFunction LPVOID lpParam?@EärendilBaggins WINAPI只是一个用于u stdcall的宏WINAPI被宏扩展为u stdcall。也可以在此处使用回调宏。所有这些都是相同的,难道不把WINAPI放在不推荐的东西之后吗?当我使用HANDLE WINAPI时,我从编译器那里得到一个警告,因为stdcall正在调用约定。只对功能有感觉。当您声明句柄WINAPI h;-这真的是时代错误德沃德真的有必要吗?因为int_uustdcall对于编译器来说很好,我不知道它是否真的有什么不同,因为我并没有为线程函数使用返回值。@Eärendilbagkins:是的,DWORD确实是必要的。int和unsigned long是不同的数据类型。如果使用int,则必须使用typecast将函数传递给CreateThread,而不应该使用typecast。如果你不得不使用类型转换来取悦编译器,那你是做错了什么。我想我会把它改成DWORD。不希望类型转换为较小的类型。@Eärendilbagkins:除非编译器在Windows上实现长64位,否则大多数使用32位,但有些使用64位,那么DWORD和int通常大小相同,但符号不同。C和C++是强类型语言。你必须使用适当的类型,C和C++都不是强类型的编程语言。但是,它们是静态类型的,因此编译器可以对不兼容的类型进行诊断。