Что означает "запрос к члену" ******* "во что-то, что не является структурой или союзом?

Есть ли легкое объяснение того, что означает эта ошибка?

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

Я встречался с ним несколько раз за время, когда я изучал C, но у меня нет подсказки относительно того, что это значит.

Ответ 1

Это также происходит, если вы пытаетесь получить доступ к экземпляру, когда у вас есть указатель, и наоборот:

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 */

Как указано в комментарии, это может быть мучительно, если кто-то идет, а typedef указатель, т.е. включает * в typedef, например:

typedef struct foo* Foo;

Потому что тогда вы получаете код, который выглядит как имеющий дело с экземплярами, когда на самом деле он имеет дело с указателями:

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

Обратите внимание, как это выглядит так, как будто оно должно быть записано a_foo.field, но это не сработает, поскольку Foo является указателем на struct. Я настоятельно рекомендую против typedef: ed указатели в C. Указатели важны, не скрывайте звездочки. Пусть они сияют.

Ответ 2

Вы пытаетесь получить доступ к члену структуры, но в том, что не является структурой. Например:

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

Ответ 3

Это может случиться и в следующем случае:

например. если мы рассмотрим функцию push стека:

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;
}

Ошибка в функции push и в комментариях. Указатель s должен быть включен в круглые скобки. Правильный код:

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

Ответ 4

Это может означать, что вы забыли включить заголовочный файл, который определяет эту структуру/объединение. Например:

Файл foo.h:

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:

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

Ответ 5

Я перечислял, возможно, все случаи, когда эта ошибка может возникать в коде и его комментариях ниже. Пожалуйста, добавьте к нему, если вы встретите больше случаев.

#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
}

Основные идеи прямые:

  • Используйте . со структурной переменной. (Случаи 2 и 4)
  • Используйте -> с указателем на структуру. (Случаи 1 и 3)
  • Если вы попадаете в структурную переменную или указатель на структурную переменную следующим указателем, то оберните указатель внутри скобки: (*ptr). и (*ptr)-> vs *ptr. и *ptr-> (все случаи, за исключением случая 1)
  • Если вы достигаете следующими указателями, убедитесь, что вы правильно достигли указателя на структуру или структуру в зависимости от того, что вам нужно. (Случай 5, особенно 5.5)

Ответ 6

также может отображаться, если:

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

foo.x=12

вместо

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

foo.x=12