web-dev-qa-db-ja.com

「構造体またはユニオンではない何かのメンバー '*******'に対する要求」とはどういう意味ですか?

このエラーの意味について簡単な説明はありますか?

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

私はCを学習している間に何度か遭遇しましたが、それが何を意味するのか手がかりがありません。

74
Pieter

ポインターがあるときにインスタンスにアクセスしようとした場合にも発生します。逆の場合も同様です。

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

コメントで指摘されているように、誰かが行き、typedefsポインタに行く、つまりtypedefに*を含めると、これは耐え難いものになります。

typedef struct foo* Foo;

なぜなら、実際にはポインタを扱っているのに、インスタンスを扱っているようにlooksのコードを取得するからです:

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

上記はa_foo.fieldと書かれているように見えますが、Fooは構造体へのポインタであるため失敗します。 Cのagainsttypedef:edポインターを強くお勧めします。ポインターは重要です。アスタリスクを非表示にしないでください。それらを輝かせてください。

109
unwind

構造体のメンバーにアクセスしようとしていますが、構造体ではないものにアクセスしています。例えば:

struct {
    int a;
    int b;
} foo;
int fum;
fum.d = 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]));
5
Kaustav Ray

このエラーがコードとそのコメントで発生する可能性があるすべてのケースを列挙しました。さらに多くのケースに遭遇した場合は、それに追加してください。

#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)
2
Mahesha999

これは、この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" */
.
.
.
1
Magnetron

次の場合にも表示されます。

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

foo.x=12

の代わりに

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

foo.x=12
0
Nahum