web-dev-qa-db-ja.com

構造体フィールド(C)を割り当てると、「エラー:配列型エラーのある式への割り当て」

私は初心者のCプログラマーです。昨日、C構造体の使用と、特定の問題の解決に関するこれらの構造体の可能なアプリケーションを学びました。しかし、Cプログラミングのこの側面を学習するためにC IDE(コードブロック16.01)を試していたときに、奇妙な問題に遭遇しました。コードは次のとおりです。

#include <stdio.h>

#define N 30

typedef struct{
     char name[N];
     char surname[N];
     int age;
} data;

int main() {
     data s1;
     s1.name="Paolo";
     s1.surname = "Rossi";
     s1.age = 19;
     getchar();
     return 0;
}

コンパイル中に、コンパイラ(WindowsのGCC 4.9.3-1)から次のエラーが報告されました。

「エラー:配列型エラーのある式への割り当て」

指導中

s1.name="Paolo" 
s1.surname="Rossi" 

している間

data s1 = {"Paolo", "Rossi", 19};

できます。私は何を間違えていますか?

28
Chief096

あなたは問題に直面しています

 s1.name="Paolo";

lHSでは、arrayタイプではなく、assignableを使用しているためです。

詳しく説明するには、C11の6.5.16章から

代入演算子は、左オペランドとして変更可能な左辺値を持たなければなりません。

そして、変更可能な左辺値に関して、§6.3.2.1章から

変更可能な左辺値は、配列型を持たない左辺値です[...]

strcpy()を使用して、配列をコピー先にする必要があります。

とは言っても、data s1 = {"Paolo", "Rossi", 19};は正常に機能します。これは、代入演算子を伴う直接的な割り当てではないためです。そこで、brace-enclosed initializer listを使用して、objectの初期値を提供しています。これは、§6.7.9の章で述べた初期化の法則に従います。

各中括弧で囲まれた初期化リストには、現在のオブジェクトが関連付けられています。指定がない場合、現在のオブジェクトのサブオブジェクトは、現在のオブジェクトのタイプに応じた順序で初期化されます。添字の昇順の配列要素、宣言の順序の構造体メンバー、および共用体の最初の名前付きメンバー。[... 。]

40
Sourav Ghosh

ここでこの例を確認してください: Accessing Structure Members

それを行う正しい方法は次のようであると説明されています:

strcpy(s1.name , "Egzona");
printf( "Name : %s\n", s1.name);
12
user5308956
typedef struct{
     char name[30];
     char surname[30];
     int age;
} data;

dataは、60文字とint *に4を合わせたメモリブロックでなければならないことを定義します

[----------------------------,------------------------------,----]
 ^ this is name              ^ this is surname              ^ this is age

これにより、スタック上のメモリが割り当てられます。

data s1;

割り当ては単に数字、時にはポインターをコピーするだけです。

これは失敗します

s1.name = "Paulo";

コンパイラは、s1.nameが64バイト長の構造体の始まりであり、"Paulo"が6バイト長のchar []であることを知っているため(C文字列の末尾\ 0のため6)
したがって、文字列へのポインタを文字列に割り当てようとしています。

"Paulo" intonameの構造体と "Rossi" intosurnameの構造体をコピーします。

memcpy(s1.name,    "Paulo", 6);
memcpy(s1.surname, "Rossi", 6);
s1.age = 1;

で終わる

[Paulo0----------------------,Rossi0-------------------------,0001]

strcpyは同じことをしますが、\0終端については知っているので、ハードコーディングされた長さは必要ありません。

または、任意の長さのpoints char配列である構造体を定義できます。

typedef struct {
  char *name;
  char *surname;
  int age;
} data;

これは作成します

[----,----,----]

これは、構造体をポインターで埋めているため機能します。

s1.name = "Paulo";
s1.surname = "Rossi";
s1.age = 1;

このようなもの

[---4,--10,---1]

4と10はポインターです。

* N.B。 intとポインターは異なるサイズにすることができ、上記のサイズ4は例として32ビットです。

10
teknopaul