web-dev-qa-db-ja.com

C-構造体の配列を初期化する

構造体の配列の初期化に問題があります。 「互換性のないポインタ型からの初期化」と「互換性のないポインタ型からの割り当て」が発生するため、正しく実行しているかどうかはわかりません。これらの警告が表示されるコードに追加しました。構造体からデータを印刷しようとすると、@@ ###などのゴミが表示されます。

typedef struct
{
    char* firstName;
    char* lastName;
    int day;
    int month;
    int year;

}student;

//配列を初期化します

    student** students = malloc(sizeof(student));
    int x;
    for(x = 0; x < numStudents; x++)
    {
        //here I get: "assignment from incompatible pointer type" 
        students[x] = (struct student*)malloc(sizeof(student));
    }

    int arrayIndex = 0;

//構造体を追加

 //create student struct
        //here I get: "initialization from incompatible pointer type"
        student* newStudent = {"john", "smith", 1, 12, 1983};

        //add it to the array
        students[arrayIndex] = newStudent;
        arrayIndex++;
17
Tony

これは間違っています:

student** students = malloc(sizeof(student));

あなたは***必要な生徒数に十分なスペース

student *students = malloc(numStudents * sizeof *students); // or sizeof (student)
for (x = 0; x < numStudents; x++)
{
    students[x].firstName = "John"; /* or malloc and strcpy */
    students[x].lastName = "Smith"; /* or malloc and strcpy */
    students[x].day = 1;
    students[x].month = 12;
    students[x].year = 1983;
}

「// add struct」セクションのコードを引き続き使用する場合は、行を変更する必要があります。

student* newStudent = {"john", "smith", 1, 12, 1983};

student newStudent = {"john", "smith", 1, 12, 1983};

タイプstudentのオブジェクトを使用してstudentへのポインターを初期化しようとしたため、「互換性のないポインタータイプからの初期化」を取得していました。

28
pmg

コンパイラの警告とは無関係ですが、最初のmallocが間違っています。あなたが欲しい:

malloc(sizeof(student *)* numStudents)

生徒への合計「numStudents」個のポインタのためのスペースを割り当てるため。この線:

students[x] = (struct student*)malloc(sizeof(student));

する必要があります:

students[x] = (student*)malloc(sizeof(student));

「構造の学生」のようなものはありません。名前のない構造体を宣言し、それをtypedefして 'student'にしました。次と比較および対比:

struct student
{
    char* firstName;
    char* lastName;
    int day;
    int month;
    int year;

};

これは「学生の構造体」タイプを作成しますが、(Cで)他の場所の学生だけでなく、学生の構造体を明示的に参照する必要があります。このルールはC++で変更されているため、コンパイラーが少し曖昧な場合があります。

はどうかと言うと:

student* newStudent = {"john", "smith", 1, 12, 1983};

それは:

student newStudent = {"john", "smith", 1, 12, 1983};

中括弧の構文は直接リテラルであり、他の場所を指す必要はありません。

編集:振り返って、aaaは私が持っている以上にこれの概要を理解しているかもしれません。誤ってどこでも余分なレベルのポインター逆参照を使用している可能性はありますか?だからあなたがしたいでしょう:

student* students = malloc(sizeof(student) * numStudents);

/* no need for this stuff: */
/*int x;
for(x = 0; x < numStudents; x++)
{
    //here I get: "assignment from incompatible pointer type" 
    students[x] = (struct student*)malloc(sizeof(student));
}*/

int arrayIndex = 0;

そして:

student newStudent = {"john", "smith", 1, 12, 1983};

//add it to the array
students[arrayIndex] = newStudent;
arrayIndex++;

NewStudentのスコープ外で使用されていない配列をサブジェクトします。そうでない場合、文字列へのポインタのコピーは正しくありません。

8
Tommy
student* students = malloc(sizeof(student)*numStudents);
int x;
for(x = 0; x < numStudents; x++)
{
    student newStudent = {"john", "smith", 1, 12, 1983}; // string copy are wrong still
    students[x] = newStudent;
}
3
Anycorn