🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

2回答

4633閲覧

C言語における構造体のアドレスについて

AdultMr.

総合スコア14

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

2クリップ

投稿2019/11/28 02:34

C言語における構造体のアドレスについて教えていただきたいです。
下記コードのように構造体を作り、実体を作りました。
そのとき実体のアドレスを調べたところ、
どちら同じアドレスが表示されました。

なぜ同じアドレスが表示されるのでしょうか。
C言語の仕様上、この場合はsも&sも同じことを表すように
変換されているのですか?

調べてみましたが、よくわからなかったため、
質問をさせていただきました。

typdef struct{ int a; int b; int c; }SAMPLE; int main(){ SAMPLE s[3]; printf("%p\n",s); printf("%p\n",&s); //どちらも同じアドレスが表示される }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ozwk

2019/11/28 02:40

それぞれ何のアドレスになることを期待してましたか?
AdultMr.

2019/11/28 02:50 編集

sのアドレスについては&s[0]と同じアドレスになることを期待していました。 実際、同じアドレスが表示されます。 &sに関してはsのアドレスを保存している領域の先頭アドレスが表示されると考えていました。 例えばですが、コードに SAMPLE *p; p = s; printf("%p\n",p); printf("%p\n",&p); と加えると、この場合は別のアドレスが表示されます。 それと同様なことが起こるのだろうと期待していました。
otn

2019/11/28 07:05

質問内容は、構造体とは何の関係も無く、配列の名前が何を意味するのかの話になってますが、質問意図は合っていますか? つまり、int s[3]; と書いても全く同じ内容の質問です。
guest

回答2

0

C言語の仕様上、この場合はsも&sも同じことを表すように

変換されているのですか?

はい、配列については、s&sも同じアドレスです。ただし、型は違います。

  • sSAMPLE *SAMPLEへのポインタ)
  • &sSAMPLE(*)[3]SAMPLEが3つの配列を指すポインタ)

投稿2019/11/28 02:39

maisumakun

総合スコア145975

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

AdultMr.

2019/11/28 03:10

ご回答いただき、ありがとうございます。 どちらも同じアドレスを指すとのこと、理解致しました。 1点、質問をさせてください。 型が異なるということですが、それによってsと&sを使い分けることがあるのでしょうか。 (SAMPLE *)型には馴染みがありますが、(SAMPLE(*)[3])型には馴染みがなく、どういった扱いができるのかが分かっておりません。 申し訳ございませんが、再度ご教授いただけないでしょうか。
guest

0

ベストアンサー

ポインタは常に基底型から派生するということを思い出してください。
例えばint*型というのはint型から派生して作られたのでした。
なぜそうなっているかといえばポインタ演算に原因があります。

c

1int32_t arr1[5]; 2int8_t arr2[5]; 3int32_t* p1 = arr1; 4int8_t* p2 = arr2; 5p1 += 1;//sizof(int32_t)==4byteポインタを進める 6p2 += 1;//sizof(int8_t)==1byteポインタを進める

ポインタへの演算の際に基底型の大きさが重要となるのでした。

さて、SAMPLE(*)[3]型を見ていきましょう。これはSAMPLE[3]型から派生していることはすぐわかると思います(Cの文法が変態すぎてわからないかもしれませんが)。

c

1SAMPLE(*)[3] p = /*なんか*/ 2p += 1;//sizeof(SAMPLE[3])だけポインタを進める

あとは同じですね。

投稿2019/11/28 12:36

yumetodo

総合スコア5852

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

AdultMr.

2019/11/29 00:40

ご解説いただき、ありがとうございました。 ポインタ演算の際に、いくつ分のアドレスが加算されるか、というのが型に応じて変わるということを失念しておりました。 分かりやすい説明をしていただき、ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問