2017-01-29 26 views
2

構造体へのポインタを理解するのに苦労しているので、いくつかのprint文でサンプルコードを書きました。構造体メンバが構造体へのポインタで更新されない

struct Student { 
     uint32_t id; 
     uint8_t marks[8]; 
     int32_t credit; 
}; 

struct Student jacob; 
struct Student *adam = &jacob; 
struct Student mary = *adam; 
mary.marks[3] = 80; 
jacob.marks[3] = 75; 
adam->marks[3] = 67; 

printf("jacob: %d\n", jacob); 
printf("&jacob: %d\n", &jacob); 
printf("adam: %d\n", adam); 
printf("*adam: %d\n", *adam); 
printf("mary: %d\n", mary); 
printf("mary.marks[3]: %d\n", mary.marks[3]); 

出力は次のようになります。

jacob: 4195856 
&jacob: -436012784 
adam: -436012784 
*adam: 4195856 
mary: 4195856 
mary.marks[3]: 80 

なぜmary.marks[3] 80の値がありますか?私が理解するところでは、がjacobのアドレスを指しているので、maryは間接的にstruct jacobを指しています。したがって、adam->marks[3] = 67の行は、同じ場所を指しているので、mary.marks[3]の値を変更します。

mary.marks[3]の値が同じままである理由を理解してもらえますか?

+4

"maryは間接的に指しています"。それは事実ではない。 'mary'はポインタではありません。 'mary'は' adam'が指しているもののコピー*を含んでいます。 – kaylum

+1

あなたは 'jacob'の内容を初期化していないので、あなたがコピーするもの(' mary'に '* adam'を割り当てる時)は未定義です。アドレスを正しく印刷する必要があります。 'printf()'(または '* adam'、または 'mary')に' jacob'を渡すべきではありません。 –

+1

p.s.将来の参考として、コンパイルできる完全な例を提供する必要があります。特に、 'main()'がありません。 –

答えて

2

簡単に言えば、struct Student jacob;というステートメントは、学生の構造の1つのコピー(スタックにもメモリにも依存しますが、答えには関係ありません)にスペースを作成します。

ステートメントstruct Student *adam = &jacob;は、adamをjacobのポインタにします。

ステートメントstruct Student mary = *adam;は、初期化されていないデータをadamが指しているもの(jacob)からmaryに割り当てられた新しいスペースにコピーします。

jacobとmaryにはスペースが割り当てられていることを理解しておくことが重要です。 adamはjacobへのポインタです。しかし、あなたがmary.marks [3] = 80と言うとき、あなたは "mary"というものに値を入れていますが、 "jacob"は変わりません。

次に、jacob.marks[3]に書き込み、その後adam->marks[3]を使用して上書きします。

あなたが何かにアドレスをプリントするときは、%pを使うべきです。あなたが%dの構造体をprintfすると、Cはちょうど整数であるかのように "あたかもあたかも"メモリを愚かに見ています。 struct Student mary = *adam;と書かれている行では、jacobを含む(まだ初期化されていない)メモリをmary用に新しく割り当てられたメモリにコピーしています。これがprintfが同じ理由です。 & maryを印刷すると、jacobやadamと同じメモリではないことがわかります。

1

maryあなたはmary*adamを割り当てたときにだけで何adamポイントの値をコピーし、だから何mary保持するadamによって指されるものではないが、ポインタではありませんので。そのため、*adamの値を変更しようとしても、maryの値に変更はありません。

2

声明jacobのみが宣言されているため

struct Student *adam = &jacob; 

は未定義の動作を起動し、それが初期化されていないメンバーです。

また、printfのデータ型に間違った指定子を使用すると、プログラムの動作が不定になります。構造体はprintfに渡すことはできません。今jacob今、あなたのコードを少し

struct Student { 
     uint32_t id; 
     uint8_t marks[3]; 
     int32_t credit; 
    }; 

int main(void) 
{ 
    struct Student jacob = {0,{0},0}; 
    struct Student *adam = &jacob; 
    struct Student mary = *adam; 
    mary.marks[3] = 80; 
    jacob.marks[3] = 75; 
    adam->marks[3] = 67; 

    printf("mary.marks[3]: %d\n", mary.marks[3]); 
} 

を変更

は、その値でstruct Studentポインタを初期化することは合法で、初期化されます。さて、jacobmaryからadamポイントがjacobコピー(jacobのメンバーへの変更がmaryでは見られないであろう)で初期化されます。
printfには80の値を持つmary.marks[3]が印刷されています。これらの記述

は、maryには影響しません。 jacob.marks[3]またはadam->marks[3]を印刷すると、変更が表示されます。

+0

説明と訂正をありがとう:) – Jspake

+0

Downvoter、説明するように気をつけますか? – haccks

1

タイプstudentの2つの構造変数とタイプstudentの構造体ポインタがあります。

a)jacobは初期化されておらず、ポインタ*adamはjacobを指しています。

b)次にjacobmaryにコピーし、ポインタ参照adamを使用してコピーしています。

c)jacobmaryは2つの異なるアドレスです。それぞれに独自のコピー のデータがあります。

d)mary.mary[3]を変更した後は、mary でない場合は、jacobにのみ更新されます。

mary.marks[3] = 80; 

それが印刷されますので、最後に更新された値です。

jacob.marks[3] = 75; //direct 
adam->marks[3] = 67; //via pointer to the same variable 

どちらも同じ場所に更新されます。上書きしています:

jacob.marks[3] 

コメントからの提案にも従ってください。

関連する問題