質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.48%
C

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

Q&A

3回答

1218閲覧

C言語のポインタについて

ora.

総合スコア10

C

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

0グッド

0クリップ

投稿2017/05/27 04:56

C言語のポインタを理解したいと思っています

イメージ説明

&と*が理解できていません。
&を変数につけると番地が取得でき、
*を変数につけて、別の変数の番地を格納すると、エイリアスとなるという
認識です。

&と*を付けた場合でそれぞれの挙動を上記で試してみました。

21行目と22行目の結果は、
変数に*をつけるとエイリアスになるという理解なので、
iが+1されるというのは理解できるのですが、

16行目と17行目の結果がなぜそうなるのかよくわかっていません。

教えてほしいです。

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

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

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

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

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

guest

回答3

0

q は6行目の代入時にiの番地ではなくiの値(5)を番地として代入しています。
ですので、qは値が5になっており、ポインタに対して+1するとC言語の決まりで型のサイズ分足されるので、
int型のサイズは4(環境によります)で5+4=9となります。
これと同じ理由で、s+1はiの番地の4バイト後ろを示しますが、番地を符号ありの整数として扱っているので4足すと-2106799988 + 4 = -2106799984 となります。
int* はエイリアスというよりも「int型の変数がある番地が入っている値」と覚えた方がいいと思います。

投稿2017/05/27 05:13

編集2017/05/27 05:32
toki_td

総合スコア2850

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

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

ora.

2017/05/27 14:32

>int* はエイリアスというよりも「int型の変数がある番地が入っている値」と>覚えた方がいいと思います。 不勉強ですみませんが、 「int型の変数がある番地が入っている値」とはどういうことですか。 「int型の変数がある番地に入っている値」ではないですよね、、?
toki_td

2017/05/27 18:00

はい、ちょっと違います。 日本語の文脈の問題になりますが「int型の変数がある番地"に"入っている」ならその値は変数の値そのものであり、ある番地に対してint型の変数 i が割り当てられていればiの値とはその番地にあるメモリの内容そのものです。 「int型の変数がある番地"が"入っている値」はint型の変数 i がメモリの位置pにすでに存在するとしてそのpを覚えておくためのある変数 j のことを言います。 プログラムではあらゆるデータはメモリ上に存在していて何かを覚えておくには必ずその分の領域が必要で、ある番地pを覚えるためにもメモリのどこかにjの領域が割り当てられます。 通常エイリアスは「別名」なのでiそのものに別名を与えている感じです。 そのため、もしC言語にエイリアスが存在するなら、iとそのエイリアスkはいついかなる時も同じ番地、同じ内容を示していて常に i == k で、&i == &k です。 実際には、ポインタ j がある変数 i を示しているなら、i == *j (値の比較)で、 &i ==j (番地の比較)となりますが、常に &i != &j であり、 i != j です(まぐれでたまたま同じになることはあるかもしれませんが)
guest

0

こんにちは。

えっと、まず5行目と6行目の定義は誤りです。警告は出なかったでしょうか?
間違っているので説明が難しいのですが、良くある間違いでもあるので説明してみます。

int i=5;
int p=&i;

pは整数型です。4バイトであることは比較的多いですが、必ずしも4バイトではありません。
&iは変数iが格納されているアドレスですね。アドレスは32ビット環境では4バイトです。(32ビット=4バイトなので) しかし、64ビット環境では8バイトです。
4バイトの記憶領域を持つ変数は、8バイトの値を記録することはできませんね。
ですので、環境によっては意図通り動作しないコードなので「誤り」なのです。

ただし、32ビット環境がメジャーだった期間は長かったです。Windows 95からここ2~3年前までくらいなので20年近く続いてますね。このケースではint p=&i;と記述しても意図通り動作するため、この誤りが結構広まっています。

int *q=i;

は、その逆ですね。qはint型変数へのポインタです。ポインタの方がint型より大きい処理系がほとんどなので意図通りに動作する場合が少なくないとは思いますが、qはポインタですから、NULL、もしくは、何か適切なメモリのあるアドレスを指すのが妥当です。
そこに5と言う決め打ちの値をアドレスとして入れてます。5番地に何が入っているのかは、OSによって異なりますし、アプリの起動ごとに変わるかもしれません。
そのようなメモリかどうか分からない謎の領域を指すポインタは不正なのです。

ですので、意味が可笑しい16行目の説明は割愛します。
なお、17行目と動作自体は同じです。

C言語のポインタは配列を指すこともあります。と言うか配列名は配列先頭へのポインタでもあるように、ポインタが配列を指すことは非常に多いです。
なので、+1することで次の要素を指すようにすると都合が良いため、C言語規格で+1は次の要素を指すと決められています。
従って、ポインタに1加えると多くの処理系ではint型のバイト数分値が増えます。(アドレスがバイト単位では無いようなCPUもあるので、そのようなCPUでは必ずしもバイト数分増えるとは限らないですが。)

お使いの処理系はアドレスがバイト単位であり、かつ、int型が4バイトと思います。なので、l12で出力したSのアドレス-210679988に対して、l17では4を加えて-210679984となっています。

投稿2017/05/27 05:28

Chironian

総合スコア23272

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

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

ora.

2017/05/27 14:29

>そこに5と言う決め打ちの値をアドレスとして入れてます。5番地に何が入>っているのかは、OSによって異なりますし、アプリの起動ごとに変わるか>もしれません。 6行目はそもそも番地として代入されているのですね、ありがとうございます。 4つずれる意味も理解できました。ありがとうございました。
guest

0

本題に対する回答はあるので,別の観点から補足します。

&を変数につけると番地が取得でき、
*を変数につけて、別の変数の番地を格納すると、エイリアスとなるという

認識です。

C言語は,&はまだしも,*がかなり使われる場所によって意味が変わってくるので,正しく把握することが重要です。

ポインタ - C言語構造体のtmpを使ったソート方法(52359)|teratail

**【左辺にあるとき】 **

pt + j: そもそも左辺にこれない
*(pt + j): pt + jの演算結果の値に対応する番地

**【右辺にあるとき】 **

pt + jpt + jの演算結果の値
*(pt + j): pt + jの演算結果の値に対応する番地にある値

↑に追記しますが,変数宣言部に*があるときは,それをポインタ変数として宣言します。ここで同時に代入を行うときは,代入すべき内容は番地です。宣言部の*は「値を番地として評価する」ということは行いません。

また,一部未定義の動作が含まれているので挙げておくと

  • int型変数の番地は必ずint *型の変数に代入する
  • int *型の表示フォーマットには必ず%pを利用する

実際に何か書く時にはこれを守ってください。番地がintであるとは限らないので。
(実際uint64_tとかunsigned long long intのほうが適切な気がする)

投稿2017/05/27 05:29

mpyw

総合スコア5223

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

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

ora.

2017/05/27 14:33

場所によって違うということは理解できましたが、どう違うのか理解できていないので、再度考えます。ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問