web-dev-qa-db-ja.com

関数に構造体を渡す

私は新しいCプログラマーであり、structを関数に渡す方法を知りたいと思いました。エラーが発生しているため、正しい構文がわかりません。コードは次のとおりです。

構造:

struct student{
    char firstname[30];
    char surname[30];
};

struct student person;

コール:

addStudent(person);

プロトタイプ:

void addStudent(struct student);

そして実際の機能:

void addStudent(person)
{
    return;
}

コンパイラエラー:

21行目:警告:疑わしいタグ宣言:struct student
行223:引数#1はプロトタイプと互換性がありません:

47
Daniel Del Core

行関数の実装は次のようになります。

void addStudent(struct student person) {

}

personは型ではなく変数です。関数パラメーターの型として使用することはできません。

また、プロトタイプが使用する関数addStudentのプロトタイプの前に構造体が定義されていることを確認してください。

40
MByD

これは、structを参照渡しする方法です。これは、関数が関数の外部のstructにアクセスし、その値を変更できることを意味します。これを行うには、構造体へのポインターを関数に渡します。

#include <stdio.h>
/* card structure definition */
struct card
{
    int face; // define pointer face
}; // end structure card

typedef struct card Card ;

/* prototype */
void passByReference(Card *c) ;

int main(void)
{
    Card c ;
    c.face = 1 ;
    Card *cptr = &c ; // pointer to Card c

    printf("The value of c before function passing = %d\n", c.face);
    printf("The value of cptr before function = %d\n",cptr->face);

    passByReference(cptr);

    printf("The value of c after function passing = %d\n", c.face);

    return 0 ; // successfully ran program
}

void passByReference(Card *c)
{
    c->face = 4;
}

これは、関数がstructのコピーを受け取り、それを変更するために外部構造にアクセスできないように、structを値で渡す方法です。外部とは、機能の外側を意味します。

#include <stdio.h>


/* global card structure definition */
struct card
{
    int face ; // define pointer face
};// end structure card

typedef struct card Card ;

/* function prototypes */
void passByValue(Card c);

int main(void)
{
    Card c ;
    c.face = 1;

    printf("c.face before passByValue() = %d\n", c.face);

    passByValue(c);

    printf("c.face after passByValue() = %d\n",c.face);
    printf("As you can see the value of c did not change\n");
    printf("\nand the Card c inside the function has been destroyed"
        "\n(no longer in memory)");
}


void passByValue(Card c)
{
    c.face = 5;
}
90
Donnell

構造体を別の関数に渡す場合、通常は上記のDonnellが提案したように実行し、代わりに参照で渡す方が適切です。

これの非常に良い理由は、そのインスタンスを作成した関数に戻ったときに反映される変更を行いたい場合に物事が簡単になることです。

これを行う最も簡単な方法の例を次に示します。

#include <stdio.h>

typedef struct student {
    int age;
} student;

void addStudent(student *s) {
    /* Here we can use the arrow operator (->) to dereference 
       the pointer and access any of it's members: */
    s->age = 10;
}

int main(void) {

    student aStudent = {0};     /* create an instance of the student struct */
    addStudent(&aStudent);      /* pass a pointer to the instance */

    printf("%d", aStudent.age);

    return 0;
}

この例では、addStudent()関数の引数は、student struct-student *sのインスタンスへのポインターです。 main()では、student構造体のインスタンスを作成し、参照演算子(&)を使用して、addStudent()関数への参照を渡します。

addStudent()関数では、矢印演算子(->)を使用してポインターを逆参照し、そのメンバーにアクセスできます(機能的には(*s).ageと同等)。

addStudent()関数で行ったすべての変更は、main()に戻るときに反映されます。これは、student構造体のインスタンスがメモリ内のどこにあるかを参照するためです。格納されます。これは、この例では「10」を出力するprintf()で示されています。

参照を渡さなかった場合、実際に関数に渡した構造体のコピーを操作します。つまり、mainに戻ったときに変更は反映されません。構造体の新しいバージョンをmainまたはそれらの行に沿った何かに戻します!

ポインターは最初は気まずいように見えるかもしれませんが、その仕組みと便利さを頭に入れてしまうと、2番目の性質になります。

8
tom1990

個人のタイプを指定する必要があります。

void addStudent(struct student person) {
...
}

また、構造体をtypedefすることで、使用するたびに構造体を入力する必要がなくなります。

typedef struct student{
...
} student_t;

void addStudent(student_t person) {
...
}
4
drew212

の代わりに:

void addStudent(person)
{
    return;
}

これを試して:

void addStudent(student person)
{
    return;
}

「学生」と呼ばれる構造をすでに宣言しているので、関数の実装で次のように指定する必要はありません。

void addStudent(struct student person)
{
    return;
}
0
afmf