Passage de Tableau en argument d'un nouveau thread en C
Je cherche à passer un tableau en argument d'une fonction dans un nouveau thread à l'aide de pthread_create, est-ce possible? J'ai un tableau d'entiers et de calculer la moyenne de la méthode qui est appelée à partir de la créer de thread méthode mais je n'arrive pas à passer mon tableau dans la méthode correctement. Voici mon code:
int nums[];
int average;
int size = 0;
void *calcAvg(int *nums[]);
int main(int argc, char *argv[]){
/* initialize an array of the integers to be passed */
nums[argc - 1];
for(int i = 0; i < argc - 1; i++){
nums[i] = atoi(argv[i + 1]);
size++;
}
/* Thread Identifier */
pthread_t avgThread;
pthread_create(&avgThread, NULL, calcAvg, nums);
pthread_join(avgThread, NULL);
printf("average= %d", average);
}
void *calcAvg(int *nums[]){
int sum;
for(int i = 0; i < size; i++){
sum += nums[i];
}
average = sum / (size);
pthread_exit(0);
}
- Cette même compiler?
nums
dansmain
n'est même pas déclaré correctement, il me semble. - Vous devriez vraiment déterminer si vous avez un moment de la compilation, de lien ou de l'exécution problème de temps. Le code ci ne devrait pas être de la compilation sans mise en garde; si elle est, vous avez besoin pour augmenter les mises en garde de niveau sur vos compilations. Et vous devriez résoudre les avertissements; n'oubliez pas, le compilateur C probablement en sait plus sur C que vous faites.
- La fonction d'un fil doit avoir la signature
void *thread_function(void *arg)
— une fonction qui prend un " universel pointer (pointeur (pointeur devoid
) en argument et renvoie un pointeur versvoid
. VotrecalcAvg()
fonction ne correspond pas à celle, de sorte que la solution de michaeltang résout ce problème. Il n'y a pas de raison particulière d'utiliserpthread_exit(0);
à la fin; étaient-ce qu'il est de mon code, j'utilisereturn 0;
— mais le résultat est le même, sauf que le compilateur ne vais pas me plaindre de ne pas retourner une valeur à partir d'une fonction qui est censé le faire. - Au sein de la fonction, la distribution de
void *
àint *
est légitime étant donné que l'entrée était à l'origine uneint
tableau, qui est d'abord converties en unint
pointeur (un pointeur vers le premier élément du tableau), puis à unevoid
pointeur vers match le prototype de fonction. Votre déclaration à l'aide deint *nums[]
parvient à utiliser deux niveaux de pointeur à l'endroit où un seul est nécessaire, il vous aurait fait mieux avecint *nums
ouint nums[]
— il y a l'équivalent dans une déclaration de fonction ou de la définition (mais seulement dans ce contexte d'ailleurs, ils sont assez différentes). - Le résidu question est une question de style — et le fil de sécurité. Vous utilisez deux variables globales,
size
etaverage
. Étant donné que votre thread principal va dormir tout seul enfant thread est en cours d'exécution, il n'y a pas de problème. Si vous aviez deux ou plusieurs threads enfants, vous auriez besoin de s'inquiéter de savoir s'il était sûr d'utiliser les variables. Étant donné quesize
est fixe une fois le filetage de démarrage (alors qu'ils avaient seulement le lire), alors que ce serait OK. Toutefois, si plusieurs threads accèdent àaverage
, vous avez vraiment besoin d'un mutex ou quelque chose de similaire pour le protéger contre les accès concurrents. - Sans doute, avec plusieurs threads, vous feriez mieux de créer une structure pour contenir le nombre d'entiers, un pointeur vers le tableau de nombres entiers, et la moyenne, et puis de passer un pointeur vers une structure distincte pour chaque thread. Bien sûr, vous pouvez simplement utiliser les threads pour calculer la somme et de calculer la moyenne dans le code principal de multiples valeurs renvoyées. Ou vous pourriez trouver une autre façon de gérer le traitement. En général, cependant, si vous avez des threads écrit à une variable globale, vous avez à assurer un accès adéquat avec les mutex ou l'équivalent.
- Merci @JonathanLeffler qui efface les choses jusqu'à une tonne!
Vous devez vous connecter pour publier un commentaire.
il y a beaucoup de problème dans votre code, j'ai corrigé certaines de compiler
j'espère que ça aidera
de la compilation: gcc-o main.c -lpthread
exécuter la commande: ./principal 2 5
de sortie: 3
gcc
et pasg++
à compiler. Vous devez également utiliser un VLA (comme le code d'origine tenté de le faire) oumalloc()
ou un contrôle de portée et d'un tableau statique plutôt que d'utilisernew
.Modifier les éléments suivants
à
La question principale que " pthread_create () prend un pointeur void comme son dernier argument. Vous essayez de passer à un tableau de pointeurs vers des entiers. Problème de "l'homme pthread_create" dans le terminal pour voir les types d'argument, vous devriez être en train de passer.
Ce que vous voulez vraiment faire est de simplement passer le de tableau d'entiers sur le fil. En C, tableau d'indexation est juste une notation pour l'arithmétique des pointeurs. Écrit
nums[i]
est equivalint à&nums[0] + i
ou tout simplementnums+i
. Le dernier cas est que le nom d'un tableau en C peut être utilisé comme un pointeur vers le premier élément du tableau.changement
void *calcAvg(int *nums[])
àvoid *calcAvg(void* thread_args)
. Puis, en calcAvg' écrireint *nums = (int*)thread_args
. Maintenant, vous pouvez utilisernums
dans cette fonction, comme si vous aviez appelécalcAvg(nums)
, qui, en essence, que vous avez fait.int *
à unvoid *
dans l'appel. En fait, cela ne devrait pas provoquer un avertissement du compilateur. Ce qui devrait provoquer un avertissement du passage devoid (*func)(int *)
pointeur de fonction à une routine attend à unevoid (*func)(void *)
.