Question

Comment dois-je écrire mon code exemple un index de tableau spécifique d'un tableau qui se trouve être un membre d'une structure? Le code suivant me donne des problèmes.

// main.c

void clean_buffers(void); // prototype

struct DEV_STATUS {
    unsigned char ADDR;
    unsigned char DEV_HAS_DATA;
    unsigned char ETH_HAS_DATA;
    unsigned char DATA[20];
};

struct DEV_STATUS g_cmdQueue[60] = {0};

void main(void) {

    clean_buffers();

    while (1) {
        ;// MCU tasks        
    }
}

void clean_buffers(void) {
    unsigned char theCount = 0;
    byte queIdx;
    for (queIdx = 0; queIdx < 59; queIdx++) {
        struct DEV_STATUS *p_struct;
        unsigned char *p_data;
        p_struct = &g_cmdQueue[queIdx];
        p_data = &p_struct->DATA;
        p_struct->ADDR = 0;
        p_struct->DEV_HAS_DATA = 0;
        p_struct->ETH_HAS_DATA = 0;
        theCount = 0;
        while(*(p_data+theCount) != 0) {
            *(p_data+(theCount++)) = 0;
        }
    }    
} // EOF main.c

Je reçois une erreur de compilation "membre struct / union prévu" sur la ligne suivante:

p_data = &p_struct->DATA;

Comment dois-je écrire un pointeur si je devais accéder, par exemple, la valeur spécifique des données membres de la structure [3]? Je suis confus, je pensais que p_data = & p_struct-> DATA; est définie, je devrais être en mesure d'obtenir en utilisant * (pdata + 3) mais je suppose que je me manque quelque chose.

Était-ce utile?

La solution

Êtes-vous sûr que vous compilez le même code affiché ici?

Si votre compilateur se plaint à cette ligne

p_data = &p_struct->DATA;

avec un message « membre struct / union prévu », votre compilateur est probablement cassé.

Notez que &p_struct->DATA est une expression parfaitement valable en C. Il n'y a absolument aucun problème avec cette expression par lui-même.

Le problème ici est juste que ce n'est pas ce que vous avez besoin dans votre cas. &p_struct->DATA renvoie un pointeur sur l'ensemble du réseau « données », i.e. un pointeur de type unsigned char (*)[20]. Vous essayez d'attribuer cette valeur à un pointeur de type unsigned char *. Cette pratique est illégale en C, étant donné que les types sont complètement différents, mais traditionnellement compilateurs C a répondu à avec un simple avertissement « incompatibilité de type » et a effectué une conversion implicite (qui, d'ailleurs, signifie que votre code d'origine, bien que « sale », devrait encore du travail comme prévu).

Même si un compilateur décide de signaler ce décalage comme une erreur (ce qui est bien), il ne devrait pas encore se plaindre de problèmes de type « membre struct / union attendus ». Il n'y a pas de tels problèmes ici.

P.S. Comme autre déjà dit, ce que vous avez vraiment besoin est p_data = &p_struct->DATA[0], mais cela ne fonctionne toujours pas expliquer le comportement étrange de votre compilateur. Se pourrait-il que « DATA » est une macro définie quelque part avant la définition des «clean_buffers de?

Ajouté 10/19/2009: Nate, dans votre code vous accédez à votre tableau à l'aide d'un theCount d'index. Puisque vous utilisez l'accès à l'index de toute façon, il n'y a vraiment aucune raison de même créer le pointeur que vous essayez de créer. Le code fonctionnera parfaitement sans aucun pointeur supplémentaire, juste acess le champ DATA directement

theCount = 0;
while (p_struct->DATA[theCount] != 0) {
  p_struct->DATA[theCount++] = 0;

(je serais probablement utiliser un cycle de for ici).

Si vous insistez vraiment sur la création de ce pointeur et en utilisant toujours l'accès à l'index, le code devrait ressembler à quelque chose comme ce qui suit (les autres déjà suggéré que plus d'une fois)

p_data = p_struct->DATA; /* or &p_struct->DATA[0] */
...
theCount = 0;
while (p_data[theCount] != 0) {
  p_data[theCount++] = 0;

De plus, vous pouvez opter pour une variante plus "exotique":)

unsigned char (*p_data)[20]; /* <- note: declared differently */
...
p_data = &p_struct->DATA; /* <- note: your original version */
...
theCount = 0;
while ((*p_data)[theCount] != 0) {
  (*p_data)[theCount++] = 0;

Cependant, le retour à une version unsigned char *p_data, puisque vous créez ce pointeur, il serait plus judicieux d'utiliser une technique de « pointeur de glissement » au lieu d'utiliser l'accès index

unsigned char *p_data;
...
p_data = p_struct->DATA; /* or &p_struct->DATA[0] */
...
while (*p_data != 0) {
  *p_data++ = 0;

Comme toujours, il est une question de préférence personnelle. Bien sûr, rien de tout cela fonctionnera jusqu'à ce que vous vous débarrasser de cette interférence de la macro.

Autres conseils

Perdre le & en   p_data = &p_struct->DATA;

p_struct est déjà un pointeur. Par la suite, l'utilisation p_data [] pour accéder à votre tableau.

Ce que vous devez écrire est l'une des deux choses:

p_data = p_struct->DATA; // DATA is the address of the first element.

ou

p_data = &p_struct->DATA[0]; // taking the address of the first element.

Il suffit de retirer le & au début, comme ceci:

p_data = p_struct->DATA;

C'est SINTAX spécial pour les tableaux (rappelez-vous qu'ils sont passés toujours comme référence) et il est équivalent à:

p_data = &p_struct->DATA[0];

Et oui, vous pouvez maintenant utiliser * (pdata + 3)

it helps.

Oops! Merci AndreyT

        struct DEV_STATUS * p_struct;         unsigned char * p_data;         p_struct = & g_cmdQueue [queIdx];         p_data = & p_struct-> DATA;

p_struct est un pointeur sur struct DEV_STATUS.
&p_struct est l'adresse d'un pointeur vers struct DEV_STATUS (ou un pointeur vers un pointeur vers une struct DEV_STATUS).

Vous voulez probablement changer cette ligne à

    p_data = p_struct->DATA;

Oh ... votre fonction clean_buffers() ne fonctionne pas "propre" le g_cmdQueue[59] élément.

Et, parce qu'il est un objet global, le g_cmdQueue de tableau est initialisé à zéro avant même la première déclaration de exceutes de main().

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top