“在非结构体或联合体中请求成员'********'”是什么意思?


81

关于此错误的含义有简单的解释吗?

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

在学习C的过程中,我曾多次遇到过它,但是我对它的含义一无所知。


更好的答案应该放在顶部。
T.Woody 2014年

Answers:


115

如果您在有指针的情况下尝试访问实例,也会发生这种情况,反之亦然:

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在C语言中使用:ed指针。指针很重要,请不要隐藏星号。让他们发光。


8
我敢打赌这是实际的问题。有时它仍然会刺痛我,特别是如果有人键入了指针类型。
约翰·博德

2
我只是补充说,如果尚未分配数组(malloc)并对其进行访问,则会出现此错误。
2012年

我知道这是自发布以来已有十多年的时间,但是最后两句话使这成为我的新收藏。“指针很重要,不要隐藏星号。让它们发光。”
艾登·比利森·库尼奥


5

在以下情况下也可能会发生:

例如。如果我们考虑堆栈的推入功能:

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

错误出现在推功能和注释行中。指针s必须包含在括号内。正确的代码:

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

2
感谢您明确指出指针(没有可怕的语言玩法)。其他答案也提到了该问题(例如“让您的指针发光”),但是在凌晨2点与GDB和Valgrind进行史诗般的战斗时,像我这样的人都赞赏您的答案明确表明了指针可能是一个问题以及如何纠正该问题。 。
Max von Hippel

3

我列举了可能在以下代码及其注释中发生此错误的所有情况。如果您遇到更多情况,请添加到它。

#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外的所有情况)
  • 如果要通过跟随指针来到达,请确保已正确到达指向struct或struct的指针。(案例5,尤其是5.5)

1

这可能意味着您忘记了包含定义此struct / union的头文件。例如:

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

0

在以下情况下也会出现:

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

foo.x=12

代替

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

foo.x=12

这两个语句之间没有区别吗?
Nick Predey '16

1
@AlaaM。几个月后回首,我错过了分号!
尼克·普雷迪
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.