私はこのコードに関して誤解しています-
typedef struct _EXP{
int x;
char* name;
char lastName[40];
}XMP
...main...
XMP a;
a.name = "eaaa";
a.lastName = strcpy(a.lastName, "bbb");
なぜ使用できないa.lastName = "bbbb";
のですか:それだけですか?
ここでタイプをよく検討してください。配列には文字列の内容がchar*
含まれていますが、単にデータを指しているだけです。その結果、アレイにはstrcpy
と友達が必要です。
さらに、ヒープまたはスタックにメモリを割り当ててchar*
から、それにコンテンツを割り当てたい場合はstrcpy
、単に割り当てるとダングリングポインタが作成されるため(つまり、メモリリーク)も使用する必要があります。
配列の場所は固定されていますが、ポインタの値(それ自体が場所です)は固定されていないためです。ポインタに新しい値を割り当てることはできますが、配列を割り当てることはできません。
内部的には、どちらも同じものです。Cの配列名はポインターですが、セマンティクスの観点からは、配列を再割り当てすることはできませんが、ポインターを再ポイントすることはできます。
あなたが書くとき
a.name = "eaaa" ;
コンパイラは、NULLで終了する文字列にメモリを割り当てeaaa\0
、その命令により、ポインタname
がその場所を指すようにします(たとえば、name
変数には、文字列の最初のバイトが存在するメモリ位置のアドレスが含まれます)。
代わりに配列がある場合は、すでにメモリ領域が割り当てられており(別のメモリ位置に割り当てることはできません!)、データ(この場合は文字列を表すバイト)でのみ埋めることができます。
これは、これの理由が何であるかについての私の理解です。
それは言語のしくみについてだと思います。C(およびC ++)は、アンマネージコードを生成します。つまり、メモリやスレッドなどを管理するために実行する環境(JVMなど)は必要ありません。したがって、コードは、OSによって直接実行される実行可能ファイルに生成されます。 。そのため、実行可能ファイルには、配列を含む各タイプ(動的タイプについては不明)に割り当てられるスペースの量などの情報が含まれています。(これが、コンパイル中にオブジェクトのサイズを知る唯一の方法であったため、C ++がヘッダーファイルを導入した理由でもあります)
したがって、コンパイラは文字の配列を検出すると、コンパイルフェーズ中に必要なスペースを計算し、その情報を実行可能ファイルに入れます。プログラムを実行すると、フローは必要なスペースの量を把握し、その量のメモリを割り当てることができます。これを複数回変更すると、たとえばC関数で、割り当てごとに前の割り当てが無効になります。だから、IMO、それがコンパイラがそれを許可しない理由です。