Was bedeutet "Anfrage nach Mitglied '*******' in etwas, das keine Struktur oder Gewerkschaft ist"?


81

Gibt es eine einfache Erklärung dafür, was dieser Fehler bedeutet?

request for member '*******' in something not a structure or union

Ich habe es in der Zeit, in der ich C gelernt habe, mehrmals erlebt, aber ich habe keine Ahnung, was es bedeutet.


Die bessere Antwort sollte nach oben akzeptiert werden.
T. Woody

Antworten:


115

Dies passiert auch, wenn Sie versuchen, auf eine Instanz zuzugreifen, wenn Sie einen Zeiger haben, und umgekehrt:

struct foo
{
  int x, y, z;
};

struct foo a, *b = &a;

b.x = 12;  /* This will generate the error, should be b->x or (*b).x */

Wie in einem Kommentar ausgeführt, kann dies unerträglich gemacht werden, wenn jemand einen typedefZeiger verwendet, dh das *in einem typedef wie folgt einschließt:

typedef struct foo* Foo;

Denn dann erhalten Sie Code, der aussieht, als würde er sich mit Instanzen befassen , obwohl es sich tatsächlich um Zeiger handelt:

Foo a_foo = get_a_brand_new_foo();
a_foo->field = FANTASTIC_VALUE;

Beachten Sie, wie das Obige aussieht, als ob es geschrieben werden sollte a_foo.field, aber das würde fehlschlagen, da Fooes ein Zeiger auf struct ist. Ich empfehle dringend gegen typedef : ed Zeiger in C. Zeiger sind wichtig, verstecken Sie Ihre Sternchen nicht. Lass sie leuchten.


8
Ich wette, das ist das eigentliche Problem. Es beißt mich gelegentlich immer noch, besonders wenn jemand einen Zeigertyp eingegeben hat.
John Bode

2
Ich möchte nur hinzufügen, dass dieser Fehler auftritt, wenn ein Array nicht zugewiesen wurde (malloc) und auf das zugegriffen wird.
Max

Ich weiß, es ist ungefähr ein Jahrzehnt oder länger her, seit dies veröffentlicht wurde, aber diese letzten beiden Sätze machten dies zu meinem neuen Lieblingsbeitrag. "Zeiger sind wichtig, verstecke deine Sternchen nicht. Lass sie leuchten."
Aiden Blishen Cuneo

20

Sie versuchen, auf ein Mitglied einer Struktur zuzugreifen, jedoch in etwas, das keine Struktur ist. Zum Beispiel:

struct {
    int a;
    int b;
} foo;
int fum;
fum.d = 5;

5

Dies kann auch im folgenden Fall passieren:

z.B. Wenn wir die Push-Funktion eines Stapels betrachten:

typedef struct stack
{
    int a[20];
    int head;
}stack;

void push(stack **s)
{
    int data;
    printf("Enter data:");
    scanf("%d",&(*s->a[++*s->head])); /* this is where the error is*/
}

main()
{
    stack *s;
    s=(stack *)calloc(1,sizeof(stack));
    s->head=-1;
    push(&s);
    return 0;
}

Der Fehler liegt in der Push-Funktion und in der kommentierten Zeile. Der Zeiger smuss in Klammern stehen. Der richtige Code:

scanf("%d",&( (*s)->a[++(*s)->head]));

2
Vielen Dank, dass Sie den Zeigerpunkt (kein schreckliches Spiel mit der Sprache) explizit gemacht haben. Andere Antworten erwähnten es (z. B. "Lass deine Zeiger leuchten"), aber um 2 Uhr morgens kämpfen Leute wie ich in einem epischen Kampf mit GDB und Valgrind, dass deine Antwort explizit zeigt, wie der Zeiger ein Problem sein kann und wie dieses Problem behoben werden kann .
Max von Hippel

3

Ich habe möglicherweise alle Fälle aufgezählt, in denen dieser Fehler im Code und seinen Kommentaren unten auftreten kann. Bitte fügen Sie hinzu, wenn Sie auf weitere Fälle stoßen.

#include<stdio.h>
#include<malloc.h>

typedef struct AStruct TypedefedStruct;

struct AStruct
{
    int member;
};

void main()
{
    /*  Case 1
        ============================================================================
        Use (->) operator to access structure member with structure pointer, instead
        of dot (.) operator. 
    */
    struct AStruct *aStructObjPtr = (struct AStruct *)malloc(sizeof(struct AStruct));
    //aStructObjPtr.member = 1;      //Error: request for member ‘member’ in something not 
                                      //a structure or union. 
                                      //It should be as below.
    aStructObjPtr->member = 1;
    printf("%d",aStructObjPtr->member); //1


    /*  Case 2
        ============================================================================
        We can use dot (.) operator with struct variable to access its members, but 
        not with with struct pointer. But we have to ensure we dont forget to wrap 
        pointer variable inside brackets.
    */
    //*aStructObjPtr.member = 2;     //Error, should be as below.
    (*aStructObjPtr).member = 2;
    printf("%d",(*aStructObjPtr).member); //2


    /* Case 3
       =============================================================================
       Use (->) operator to access structure member with typedefed structure pointer, 
       instead of dot (.) operator. 
    */
    TypedefedStruct *typedefStructObjPtr = (TypedefedStruct *)malloc(sizeof(TypedefedStruct));
    //typedefStructObjPtr.member=3;  //Error, should be as below.
    typedefStructObjPtr->member=3;
    printf("%d",typedefStructObjPtr->member);  //3


    /*  Case 4
        ============================================================================
        We can use dot (.) operator with struct variable to access its members, but 
        not with with struct pointer. But we have to ensure we dont forget to wrap 
        pointer variable inside brackets.
    */
    //*typedefStructObjPtr.member = 4;  //Error, should be as below.    
    (*typedefStructObjPtr).member=4;
    printf("%d",(*typedefStructObjPtr).member);  //4


    /* Case 5
       ============================================================================
       We have to be extra carefull when dealing with pointer to pointers to 
       ensure that we follow all above rules.
       We need to be double carefull while putting brackets around pointers.
    */

    //5.1. Access via struct_ptrptr and  ->
    struct AStruct **aStructObjPtrPtr = &aStructObjPtr;
    //*aStructObjPtrPtr->member = 5;  //Error, should be as below.
    (*aStructObjPtrPtr)->member = 5;
    printf("%d",(*aStructObjPtrPtr)->member); //5

    //5.2. Access via struct_ptrptr and .
    //**aStructObjPtrPtr.member = 6;  //Error, should be as below.
    (**aStructObjPtrPtr).member = 6;
    printf("%d",(**aStructObjPtrPtr).member); //6

    //5.3. Access via typedefed_strct_ptrptr and ->
    TypedefedStruct **typedefStructObjPtrPtr = &typedefStructObjPtr;
    //*typedefStructObjPtrPtr->member = 7;  //Error, should be as below.
    (*typedefStructObjPtrPtr)->member = 7;
    printf("%d",(*typedefStructObjPtrPtr)->member); //7

    //5.4. Access via typedefed_strct_ptrptr and .
    //**typedefStructObjPtrPtr->member = 8;  //Error, should be as below.
    (**typedefStructObjPtrPtr).member = 8;
    printf("%d",(**typedefStructObjPtrPtr).member); //8

    //5.5. All cases 5.1 to 5.4 will fail if you include incorrect number of *
    //     Below are examples of such usage of incorrect number *, correspnding
    //     to int values assigned to them

    //(aStructObjPtrPtr)->member = 5; //Error
    //(*aStructObjPtrPtr).member = 6; //Error 
    //(typedefStructObjPtrPtr)->member = 7; //Error 
    //(*typedefStructObjPtrPtr).member = 8; //Error
}

Die zugrunde liegenden Ideen sind klar:

  • Verwendung .mit Strukturvariable. (Fälle 2 und 4)
  • Mit ->Zeiger auf Struktur verwenden. (Fälle 1 und 3)
  • Wenn Sie die Strukturvariable oder den Zeiger auf die Strukturvariable erreichen, indem Sie dem Zeiger folgen, wickeln Sie den Zeiger in die Klammer: (*ptr).und (*ptr)->vs *ptr.und *ptr-> (Alle Fälle außer Fall 1)
  • Wenn Sie mit folgenden Zeigern erreichen, stellen Sie sicher, dass Sie den Zeiger auf struct oder struct korrekt erreicht haben, je nachdem, was gewünscht wird. (Fall 5, insbesondere 5.5)

1

Dies kann bedeuten, dass Sie vergessen haben, eine Header-Datei einzuschließen, die diese Struktur / Vereinigung definiert. Zum Beispiel:

foo.h Datei:

typedef union
{
    struct
    {
        uint8_t FIFO_BYTES_AVAILABLE    : 4;
        uint8_t STATE                   : 3;
        uint8_t CHIP_RDY                : 1;
    };
    uint8_t status;
} RF_CHIP_STATUS_t;

RF_CHIP_STATUS_t getStatus();

main.c Datei:

.
.
.
if (getStatus().CHIP_RDY) /* This will generate the error, you must add the  #include "foo.h" */
.
.
.

0

kann auch erscheinen, wenn:

struct foo {   int x, int y, int z }foo; 

foo.x=12

anstatt

struct foo {   int x; int y; int z; }foo; 

foo.x=12

Gibt es keinen Unterschied zwischen diesen beiden Aussagen?
Nick Predey

1
@AlaaM. Wenn ich Monate später zurückblicke, habe ich die Semikolons verpasst!
Nick Predey
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.