1

我的代码

#include <pthread.h>
#include <unistd.h>
#include <stdio.h>

void * thread_func1(void *args)
{
    printf("thread 1 returning\n");
    return ((void *)1);
}

void * thread_func2(void *args)
{
    printf("thread 2 exiting\n");
    pthread_exit((void *)2);
}

int main(void)
{
    int err;
    pthread_t tid1, tid2;
    void *tret;

    err = pthread_create(&tid1, NULL, thread_func1, NULL);
    if(err)
    {
        printf("cannot create thread 1\n");
    }
    err = pthread_create(&tid2, NULL, thread_func2, NULL);
    if(err)
    {
        printf("cannot create thread 2\n");
    }

    err = pthread_join(tid1, &tret);
    if(err)
    {
        printf("thread 1 join error\n");
    }
    printf("thread 1 return code:%d\n", (int)tret);

    err = pthread_join(tid2, &tret);
    if(err)
    {
        printf("cannot join thread 2\n");
    }
    printf("thread 2 return code:%d\n", (int)tret);
    exit(0);
}

编译代码时,有两个警告:

join.c:44: warning: cast from pointer to integer of different size
join.c:51: warning: cast from pointer to integer of different size

我阅读了以下的手册页pthread_join

 int pthread_join(pthread_t thread, void **retval);
   If retval is not NULL, then pthread_join() copies the exit status of
   the target thread (i.e., the value that the target thread supplied to
   pthread_exit(3)) into the location pointed to by *retval.  If the
   target thread was canceled, then PTHREAD_CANCELED is placed in
   *retval.

根据我的理解,存在状态(int类型)存储tret在我的代码中,所以我使用(int)转换void *int,但是上面的警告被抛出,所以,我的问题是:

如何修改我的代码以清除警告?

4

3 回答 3

3

这些警告是无害的(在这种情况下),可以放心地忽略。

警告来自这些行的演员表:

printf("thread 1 return code:%d\n", (int)tret);  // line 44
...
printf("thread 2 return code:%d\n", (int)tret);  // line 51

编译器抱怨您将指针(可能是 64 位)向下转换为更小的 32 位整数。由于各种原因,许多遗留的 C 代码喜欢在指针和整数之间来回转换。在过去,指针与整数大小相同,所以这没问题;但是当 64 位目标变得更加普遍时,这突然变得很危险,因为如果您有一个指向地址 0x00000000'ffffffff 上方的 64 位指针,则在将其转换为整数时会丢失高位。当您稍后将其转换回 64 位指针时,您的指针将不正确,并且尝试使用它会崩溃或静默损坏内存。

此处的警告只是试图帮助您避免这些潜在问题。如果指针中的值实际上不是真正的指针,就像在这种情况下,那么如果你知道它的值永远不会超过 0xffffffff,那么将它转换为整数是完全安全的。

有几种方法可以抑制警告。您可以在编译器的命令行中全局禁用它(不推荐);您可以#pragma在代码周围使用 a 暂时禁用警告(不可移植);或者,您可以使用一些巧妙的转换来解决它。

有两种数据类型intptr_tuintptr_t,它们的行为就像普通整数一样——你可以向上/向下转换为其他整数类型,你可以在那时进行各种算术运算,等等——但它们保证足够大以容纳指针值。在 32 位系统上,intptr_t将(至少)32 位宽;在 64 位系统上,intptr_t将(至少)64 位宽。这两种类型之间的唯一区别是有intptr_t符号uintptr_t而无符号。

由于编译器知道这些类型总是足够大以保存指针值,因此当您将指针转换为指向它们或从它们转换为指针时,它不会警告您。一旦进入整数域,您就可以转换为普通int值而不必担心警告。所以这段代码应该消除你的警告:

#include <stdint.h>
...
printf("thread 1 return code:%d\n", (int)(intptr_t)tret);  // line 44
printf("thread 2 return code:%d\n", (int)(intptr_t)tret);  // line 51
于 2014-01-28T05:07:38.950 回答
-1
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
void * thread_func1(void *args)
{
    printf("thread 1 returning\n");
    return ((void *)1);
}

void * thread_func2(void *args)
{
    printf("thread 2 exiting\n");
    pthread_exit((void *)2);
}

int main(void)
{
    int err;
    pthread_t tid1, tid2;
    int *tret = malloc(sizeof(int)); 

    err = pthread_create(&tid1, NULL, &thread_func1, NULL);
    if(err)
    {
        printf("cannot create thread 1\n");
    }
    err = pthread_create(&tid2, NULL, &thread_func2, NULL);
    if(err)
    {
        printf("cannot create thread 2\n");
    }

    err = pthread_join(tid1, (void *)tret);
    if(err)
    {
        printf("thread 1 join error\n");
    }
    printf("thread 1 return code:%d\n", *(tret));

    err = pthread_join(tid2, (void *)tret);
    if(err)
    {
        printf("cannot join thread 2\n");
    }
    printf("thread 2 return code:%d\n", *(tret));
    exit(0);
}

第一次我只删除了警告,没有执行你的代码......

这是您的所有代码..执行时没有警告:)

于 2014-01-28T04:47:21.537 回答
-1

试试这个应该可以正常工作

作为 thread_join 的定义,它期望void **不是 void 指针

err = pthread_join(tid1, (Void **)&tret);

并在它返回值后推迟它

printf("thread 1 return code:%d\n", *(int *)tret);
于 2014-01-28T05:19:05.770 回答