2010-04-05 3 views
6

Salut, je travaille avec C et j'ai une question sur l'attribution de pointeurs. Car et _car ont la même déclaration alors pourquoi ai-je une erreur sur les types incompatibles? Ma conjecture est que cela a quelque chose à voir avec le fait qu'ils soient des pointeurs (parce qu'ils sont des pointeurs vers des tableaux de char *, n'est-ce pas?) Mais je ne vois pas pourquoi c'est un problème. Quand j'ai déclaré char * car; au lieu de char * car[MAXINT];, il compile bien. mais je ne vois pas comment cela pourrait m'être utile plus tard quand j'aurais besoin d'accéder à certaines informations en utilisant l'index, ce serait très agaçant d'accéder à cette info plus tard. en fait, je ne suis même pas sûr que je vais dans la bonne direction, peut-être qu'il y a une meilleure façon de stocker un tas de chaînes au lieu d'utiliser array of char *?c types incompatibles dans l'affectation, problème avec les pointeurs?

EDIT: Je ne voulais pas utiliser INT_MAX (valeur maximum int), il est juste un autre int, qui est d'environ 20.

Répondre

3

Vous créez un nouveau tableau de taille MAXINT. Je pense que vous voulez créer un pointeur vers un tableau de taille MAXINT.

Création d'un pointeur sur un tableau de l 'char *:

Ce qui suit est un tableau de taille MAXINT à char * éléments:

char * car[MAXINT]; 

Ce qui suit est un pointeur vers: un tableau de taille MAXINT à char * éléments:

char* (*car)[MAXINT]; 

ce qui suit comment vous définissez un pointeur sur: un tableau de taille MAXINT char * éléments:

char* (*car)[MAXINT]; 
car = &arg->_car; 

Autres erreurs de syntaxe dans la question:

  • Vous devez avoir un point-virgule après votre définition de struct.Vous devez utiliser foo* et non foo. Il doit donc être:
    struct foo* thing = (struct foo *) arg;
  • Vous devez utiliser thing pas arg:
    bar = thing->_bar;
    car = thing->_car;
+0

Merci, ce dont j'avais besoin, c'était un pointeur sur le tableau de char *. Je pense que c'est ce dont j'avais besoin (croise le doigt) –

+0

@Fantastic Fourier: D'accord, vous avez besoin d'un pointeur vers un tableau, dont les éléments sont char *. d'autres réponses ont mentionné un pointeur vers un tableau char * qui n'est pas le même. –

5

car et _car sont les deux tableaux, et vous ne pouvez pas affecter des tableaux en C (sauf lorsque le tableau est incorporé dans une structure (ou union) et que vous faites une affectation de structure).

Ce sont également des tableaux de pointeurs vers char, plutôt que des pointeurs vers des tableaux de char. Ce que vous avez écrit dans le code est probablement ce que vous voulez - vous pouvez stocker des pointeurs jusqu'à des noms MAXINT dans le tableau. Cependant, vous devez décrire le type correctement - comme un tableau de pointeurs vers des pointeurs char ou char.

Un pointeur sur un tableau de caractères ressemblerait à ceci:

char (*car)[MAXINT]; 

Et un point à un tableau de pointeurs de caractères (merci, Brian) ressemblerait à ceci:

char *(*car)[MAXINT]; 

Méfiez-vous des MAXINT; cela pourrait être un très grand tableau (sur Linux, <values.h> définit MAXINT comme INT_MAX, qui est au moins 2 -1).


Le code ressemble à:

struct foo 
{ 
    int _bar; 
    char * _car[MAXINT]; 
} 

int foofunc (void * arg) 
{ 
    int bar; 
    char * car[MAXINT]; 
    struct foo thing = (struct foo *) arg; 
    bar = arg->_bar; // this works fine 
    car = arg->_car; // this gives compiler errors of incompatible types in assignment 
} 

Ni l'affectation à la barre, ni voiture devrait compiler du tout - arg est un void *. Vous vouliez probablement utiliser thing dans une certaine forme ou forme.Comme Brian a noté, il y a des problèmes là aussi:

Soit vous voulez:

int foofunc(void *arg) 
{ 
    int bar; 
    char *car[MAXINT]; 
    struct foo thing = *(struct foo *)arg; 
    bar = thing._bar; // this works fine 
    car = thing._car; // this is still an array assignment 
    ...other code using bar and car... 
} 

Ou vous voulez:

int foofunc(void *arg) 
{ 
    int bar; 
    char *car[MAXINT]; 
    struct foo *thing = (struct foo *) arg; 
    bar = thing->_bar; // this works fine 
    car = thing->_car; // this is still an array assignment 
    ...other code using bar and car... 
} 

Ou bien:

int foofunc(void *arg) 
{ 
    struct foo *thing = (struct foo *) arg; 
    int bar   = thing->_bar; // this works fine 
    char *car[MAXINT] = thing->_car; // this is still an array assignment 
    ...other code using bar and car... 
} 

Enfin, en traitant l'assignation de tableau, en C, vous pouvez utiliser raisonnablement memmove() pour ce faire:

int foofunc(void *arg) 
{ 
    struct foo *thing = (struct foo *) arg; 
    int bar   = thing->_bar; // this works fine 
    char *car[MAXINT]; 
    memmove(car, thing->_car, sizeof(car)); 
    ...other code using bar and car... 
} 

La fonction similaire memcpy() ne pas sémantique fiable si les zones à copier se chevauchent, alors que memmove() fait; il est plus simple de toujours utiliser memmove() car cela fonctionne toujours correctement. En C++, vous devez être prudent sur l'utilisation de memmove() (ou memcpy()). Dans ce code, il serait assez sûr, mais comprendre pourquoi est non-trivial.

Vous devez savoir que vous ne faites que copier des pointeurs ici - vous ne copiez pas les chaînes pointant vers. Si quelque chose d'autre change ces chaînes, cela affecte à la fois les valeurs vues via car et la variable dans le code appelant.

Un dernier point - pour l'instant: êtes-vous sûr que vous avez besoin de l'argument de la fonction en tant que void *? Il ouvre le code à toutes sortes d'abus qui peuvent être évités si la fonction est déclarée prendre un 'struct foo *' à la place (ou même un 'const struct foo *').

+0

Je pense qu'il veut un tableau de pointeurs à char, puisque chaque pointeur-à-caractère semble représenter un nom de voiture . Cependant, Brian a un point qu'il peut être en mesure d'utiliser un pointeur sur le tableau, plutôt que de le copier. –

+0

@Matthew: Je suis d'accord qu'il veut probablement ce qu'il a écrit dans le code. Cependant, sa description de ce qu'il a est erronée - c'est ce que j'ai essayé de dire (mais de toute évidence, cela n'a pas été assez clair). –

+0

Un pointeur vers un tableau de caractères n'est pas identique à un pointeur vers un tableau de pointeurs de caractères. –

2

Vous ne pouvez pas affecter à une baie comme vous le faites. Vous pouvez faire une copie par élément.

for(int i = 0; i < MAXINT; i++) 
{ 
    car[i] = (arg->_car)[i] 
} 

Notez que si si les chaînes ne sont pas constants, vous devrez peut-être utiliser strcpy.

+0

S'il utilisait 'strcpy()', il devrait faire attention à l'espace dans lequel les chaînes devraient être copiées. Cependant, si les chaînes ne sont pas constantes, alors les changements effectués à un endroit (via une variable) peuvent apparaître de manière inattendue dans l'autre (les chaînes pointées par l'autre variable changeront également puisque les deux ensembles pointent vers le même espace). –

0

notation Array en C est légitimement source de confusion; votre code ne signifie pas ce que vous pensez que cela signifie.

arg->_car signifie "l'adresse du tableau _car". De même, car signifie "l'adresse du tableau car". Si vous essayez de copier le contenu de _car à la voiture, cela le fera:

memcpy(car, _car, MAXINT); 

Mais votre vraie question, je pense, est « ce qui est la meilleure façon de stocker une liste de chaînes? » Cette réponse est: une liste dynamique (une liste qui se développe automatiquement lorsque vous ajoutez des éléments).

Vous souhaitez déclarer comme ceci:

#define CARSIZE 65 
int numCars = 0; 
char **car; /* a list of addresses, each one will point to a string */ 

Pour ajouter une voiture:

char *newCar = malloc(CARSIZE); /* make room */ 
strncpy(newCar, "Mercedes", CARSIZE); /* newCar has the address of the string */ 
car[numCars++] = newCar; /* store it */ 

Pour la liste des voitures:

int n; 
for (n = 0; n < numCars; ++n) 
    printf("%s\n", car[n]); 

Pour retirer la voiture à la position n :

free(car[n]); /* release the memory */ 
/* condense the list of pointers */ 
for (; n < numCars - 1; ++n) 
    car[n] = car[n+1]; 

Ceci est complètement routinier dans C. NOTE: Ce qui précède est au sommet de ma tête et pas copié d'un programme de travail, donc je ne peux pas promettre que tous les * sont au bon endroit. Je pense qu'il s'agit d'une tâche à faire, donc je ne veux pas vous donner tout ...

+0

c'est pour mes réseaux où le tableau est utilisé pour conserver les noms des connexions entrantes (le nombre de connexions est maxxé à SOME_NUMBER qui est 20). Donc, je pense que je devrais rester avec statique, plutôt que dynamique. –