强制转换和参数警告

Casting and Argument Warnings

本文关键字:参数 警告 转换      更新时间:2023-10-16

我有以下代码,编译和执行没有错误,但编译器显示一些我想"解决"的警告。

这是我的代码:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
typedef struct s_Barrier{
    sem_t sEntry, sMutEx, sExit;
    int nTaskInBarrier;
}Barrier;
void createTasks(pthread_t threads[]);
void task(void *arg);
void initBarrier(Barrier *pb, int n);
void destroyBarrier(Barrier *pb);
void waitInBarrier(Barrier *pb);

Barrier barrier;
int nTask = 5;

int main(void) {
    pthread_t threads[nTask];
    initBarrier(&barrier,nTask);
    createTasks(threads);
    destroyBarrier(&barrier);
    return 0;
}
void createTasks(pthread_t threads[]){
    int i;
    for(i = 0; i < nTask; i++){
        pthread_create(&threads[i], NULL, task, (void*)i);
    }
    for(i = 0; i < nTask; i++){
        pthread_join(threads[i], NULL);
    }
}
void initBarrier(Barrier *pb, int n){
    pb->nTaskInBarrier = 0;
    sem_init(&pb->sEntry,0,n);
    sem_init(&pb->sExit,0,1);
    sem_init(&pb->sMutEx,0,1);
}
void destroyBarrier(Barrier *pb){
    sem_destroy(&pb->sEntry);
    sem_destroy(&pb->sExit);
    sem_destroy(&pb->sMutEx);
}
void task(void *arg){
    int i = (int) arg;
    while(1){
        printf("I'm thread %dn",i);
        waitInBarrier(&barrier);
    }
}
void waitInBarrier(Barrier *pb){
    int x;
    int i;
    sem_wait(&pb->sEntry);
    sem_wait(&pb->sMutEx);
    x = ++pb->nTaskInBarrier;
    sem_post(&pb->sMutEx);
    if(x < nTask){
        sem_wait(&pb->sExit);
    }else{
        for(i = 0; x < nTask ; i++){
            sem_post(&pb->sExit);
        }
    }
    sem_wait(&pb->sMutEx);
    x = --pb->nTaskInBarrier;
    sem_post(&pb->sMutEx);
    if(x == 0){
        for(i = 0; x < nTask ; i++){
            sem_post(&pb->sEntry);
        }
    }
}

当我使用"gcc -o Barrier 3.4 . Barrier.c -pthread"编译时,得到以下警告。

3.4Barrier.c: In function ‘createTasks’:
3.4Barrier.c:47:43: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
   pthread_create(&threads[i], NULL, task, (void*)i);
                                       ^
    3.4Barrier.c:47:37: warning: passing argument 3 of ‘pthread_create’ from incompatible pointer type [-Wincompatible-pointer-types]
   pthread_create(&threads[i], NULL, task, (void*)i);
                                 ^
In file included from 3.4Barrier.c:13:0:
/usr/include/pthread.h:233:12: note: expected ‘void * (*)(void *)’ but argument is of type ‘void (*)(void *)’
 extern int pthread_create (pthread_t *__restrict __newthread,
        ^
    3.4Barrier.c: In function ‘task’:
    3.4Barrier.c:70:10: warning: cast from pointer to integer of different size     [-Wpointer-to-int-cast]
  int i = (int) arg;

第一个问题是task应该返回void*,而不是void,正如pthread_create的原型所指定的那样:

void* task(void *arg) {
    // ...
    return NULL;
}

这很容易解决。

第二个问题是你不应该这样传递i——你不应该将int强制转换为void*。将i传递给task的一种方法是分配一小块内存空间并使用它1:

for(i = 0; i < nTask; i++){
    int *pi = malloc(sizeof(int));
    if (pi == NULL) { 
        // Something wrong...
    }
    *pi = i;
    pthread_create(&threads[i], NULL, task, pi);
}

:

void* task(void *arg){
    int i = *(int*)arg; // Cast to `int*` and then dereference.
    free(arg); // Don't forget this!
    while(1){
        printf("I'm thread %dn",i);
        waitInBarrier(&barrier);
    }
    return NULL;
}

1不要尝试将(void*)&i直接传递给pthread_create,因为不能保证*(int*)arg将在for循环的增量之前被评估,所以您可能会得到一些奇怪的行为,i在您读取其值之前被更改

修改

void createTasks(pthread_t threads[]){
  int i;
  for(i = 0; i < nTask; i++){
      pthread_create(&threads[i], NULL, task, (void*)i);
  }

:

void createTasks(pthread_t threads[]){
  int i;
  for(i = 0; i < nTask; i++){
      int *arg = malloc(Sizeof(int));
      *arg = i;
      pthread_create(&threads[i], NULL, task, (void*)arg);
  }

然后改变:

void task(void *arg){
    int i = (int) arg;
    while(1){
        printf("I'm thread %dn",i);
        waitInBarrier(&barrier);
    }
}

void *task(void *arg){
    int i = *((int *) arg);
    free(arg);
    while(1){
        printf("I'm thread %dn",i);
        waitInBarrier(&barrier);
    }
    return 0;
}

这将避免你遇到的错误,因为它解决了void和int大小不同的问题。

它还将为任务

提供写返回类型

做一些改动:1-第13行和第59行的void *task(void *arg);因为在pthread_create函数

中,task被用作指向函数的指针

int pthread_create(pthread_t *thread, const pthread_attr_t *attr);void * ( start_routine)(空白), void * arg);

2- int i = *((int *)arg);在第60行3-像这样编译gcc Barrier.c -lpthread