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

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

詳細はこちら
C

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

ポインタ

ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

4回答

1541閲覧

ポインタで宣言した変数はどこに保持されているのか

apa

総合スコア68

C

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

ポインタ

ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2021/03/05 04:49

class P
{
public:
int* pp;
int* ppp;
int x;
};

int main()
{
P* p;
printf("%d\n", sizeof(p)); //4byte
p = new P;
printf("%d\n", sizeof(p)); //4byte
p->pp = new int(0);
p->ppp = new int(0);
printf("%d", sizeof(p)); //4byte
}

ポインタについてわからないことがあり質問したいです。

1 newする前の変数pが4byte持っていましたが、このメモリはどこのメモリ領域に保持されているのか?
2 p->pp p->pppをnewしたのにも関わらずメモリ量が4byteなのはなぜか? sizeof()はヒープ領域のメモリを見ることができないのか?

以上2点がわかりません よろしくお願いいたします。

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

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

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

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

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

guest

回答4

0

sizeof は「型の大きさ」を見る仕組みになっていて、原則としては与えられた式を評価しません。 (VLA 関連で例外はあります。)

この場合は p という式を与えたらコンパイラは p の型が P* であることを知っていますから P* の大きさを返すだけなのです。

ポインタが指す先の大きさを知りたいなら sizeof(*p) とすれば良いです。 このとき *p は評価されず型 P を導き出すために使うだけなので p が未初期化でも問題ありません。


ところで sizeof の返却値の型は size_t 型であって int ではないので %zu を使うほうが好ましいですね。

投稿2021/03/05 05:29

SaitoAtsushi

総合スコア5684

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

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

0

2 p->pp p->pppをnewしたのにも関わらずメモリ量が4byteなのはなぜか? sizeof()はヒープ領域のメモリを見ることができないのか?

はい、sizeof(p)は常にポインタ自体のサイズです。

投稿2021/03/05 05:04

maisumakun

総合スコア145963

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

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

0

ベストアンサー

1 newする前の変数pが4byte持っていましたが、このメモリはどこのメモリ領域に保持されているのか?

まず、pはポインタ変数です。
整数変数が、変数の割り当てられた領域に整数のデータを格納するように、
ポインタ変数は、変数の割り当てられた領域にポインタ(アドレス)のデータを格納します。
整数変数が値が代入されるされないに関わらず、領域を持っているように、
ポインタ変数もまた、値が代入されるされないに関わらず、領域を持っています。
sizeof演算子によって、求められるのは、この変数としての割り当てられた領域のサイズです。

pは関数内で宣言されたローカル変数ですので、スタックメモリ内に領域は確保されます。

2 p->pp p->pppをnewしたのにも関わらずメモリ量が4byteなのはなぜか? sizeof()はヒープ領域のメモリを見ることができないのか?

上で書いたように、sizeof演算子によって求められるのは、p自体に割り当てられた領域のサイズであり、newで確保された領域のサイズではありません。

整数変数の中身の値がどう変化しようと、変数のサイズが変化したりしないのと同様に、
ポインタ変数の中身の値がどう変化しようと、ポインタ変数自体のサイズもまた変化しません。
なので、値を何度書き換えても、サイズが変化しないというのは、当然の結果です。

投稿2021/03/05 19:58

amiya

総合スコア1218

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

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

apa

2021/03/06 02:50

返信ありがとうございます 上で書いたように、sizeof演算子によって求められるのは、p自体に割り当てられた領域のサイズであり、newで確保された領域のサイズではありません。 ← ではnewで確保された変数は別のヒープメモリ領域に行くということでしょうか? 配列は縦にデータが入っている感覚ですが、ポインタは飛び飛びになってしまうということですか
amiya

2021/03/06 03:17

newで、確保されたものとポインタ変数の領域には、何の関係もありません。 newで確保された配列の領域と、 ポインタ変数の領域とは、全く個別に存在しています。 そして、代入演算子を使うことで、配列の領域の先頭アドレスを、ポインタ変数の領域に書き込んでいる。 それだけの関係になります。 ポインタは単独の変数ですので、飛び飛びという概念はありません。 1つ分のポインタの領域は連続したエリアにまとめて確保されます。 2つ以上のポインタ変数があったとして、スタックに積まれるので、物理的には連続するかもしれませんが、 それはただのたまたまなので、プログラム的には意味はありません。 他の変数と同じです。
apa

2021/03/06 04:18 編集

なるほど 理解できました。 では自分のPCですと sizeof(p)が4バイトでしたが、 正直これが1バイトだろうが、2バイトだろうが、代入するからかわらないよ~という感じですね。
apa

2021/03/06 04:17 編集

メモリの概念が間違っていたかもしれません 4byteがintの変数が格納されるとばかり思っていましたが、 あくまで入るのは変数のアドレスでそれは32ビットあり ヒープ領域へのアクセスが可能になる。となるとint*pてあんまり意味がないような気がしますが・・ 4バイトをヒープ領域へのアクセスアドレスをもちヒープ領域でも4バイトint整数を表す値を持つ。 言葉にするのが難しいですが、理解できましたありがとうございました!!
amiya

2021/03/06 05:13

別にヒープ領域にアクセスするためにあるわけではありません。 ポインタが管理するのはただのアドレスです。どこの、というのはありません。 全てのアドレスを扱えます。
guest

0

1 newする前の変数pが4byte持っていましたが、このメモリはどこのメモリ領域に保持されているのか?

C++

1int main() 2{ 3 int i; 4 P* p; 5}

↑のコードには2つの変数(ip)があるわけですが,

  • iはどこに保持されているのか?
  • pはどこに保持されているのか?

前者と後者は,まぁ,一緒でしょう.
iがスタック領域に取られるとすれば,pも同様でしょう.

投稿2021/03/05 05:21

fana

総合スコア11985

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問