私は新しい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はプロトタイプと互換性がありません:
行関数の実装は次のようになります。
void addStudent(struct student person) {
}
person
は型ではなく変数です。関数パラメーターの型として使用することはできません。
また、プロトタイプが使用する関数addStudent
のプロトタイプの前に構造体が定義されていることを確認してください。
これは、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;
}
構造体を別の関数に渡す場合、通常は上記の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番目の性質になります。
個人のタイプを指定する必要があります。
void addStudent(struct student person) {
...
}
また、構造体をtypedefすることで、使用するたびに構造体を入力する必要がなくなります。
typedef struct student{
...
} student_t;
void addStudent(student_t person) {
...
}
の代わりに:
void addStudent(person)
{
return;
}
これを試して:
void addStudent(student person)
{
return;
}
「学生」と呼ばれる構造をすでに宣言しているので、関数の実装で次のように指定する必要はありません。
void addStudent(struct student person)
{
return;
}