ポインタを理解する

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
Rittai_3D
記事: 524
登録日時: 7年前

ポインタを理解する

#1

投稿記事 by Rittai_3D » 6年前

どうも、3Dです。

今回は、前回のトピック( http://dixq.net/forum/viewtopic.php?f=3&t=13591 )で出てきたポインタについての事です。

自分はポインタが苦手で、C言語を勉強し始めて既に1年が経過しましたが未だに理解できません。

コード:

// ポインタの自分の理解度
int a;  //  メモリ上に4バイト分の領域を確保して、領域の名前をaとする。(ですよね?)
int* b; //  メモリ上に4バイト分の領域を確保し、そこにアクセスするための名前をbとする(この辺から間違えそう…
a=4;   // メモリ上にaという名前で確保された領域に4を代入する(ですよね?)
b=&a; // bで確保されたメモリ上の領域の場所が渡される?(頭の中に???がいっぱい出てきます)
と理解が曖昧です。このトピックでポインタを克服したいと思います。

上の解釈で間違っていること、若しくは前回のトピックのことなどが有りましたら教えて下さい。

また、前回のトピックでへにっくす様が貼って下さったリンクを読みましたが、わかりそうでわからないのでモヤモヤしています。
初心者です

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: ポインタを理解する

#2

投稿記事 by softya(ソフト屋) » 6年前

まず、
int* b; // メモリ上に4バイト分の領域を確保し、領域の名前をbとする。この変数はポインタ型である。
って感じですかね。

それぞれ図を書いてみてはどうでしょうか? 型 変数名 仮のアドレス(0x1000など) 値 を記載してください。
① 2行目、3行目の状態。値は不定と書いてください。
② 4行目、5行目の状態。出来ればbとaの関係も矢印でお願いします。

【補足】
ちなみにポインタが4バイトかは環境依存です。
2バイトや8バイトもあります。64bitOSだと8バイトですね。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

KORYUOH
記事: 44
登録日時: 7年前

Re: ポインタを理解する

#3

投稿記事 by KORYUOH » 6年前

概念でよく言われるのが名簿の関係です
宣言と名簿
int a; ○○さん
int* b; xx番の人

という考え方です。

aさんとかbさんとかだと名前を知っていないと呼び出せませんが、
10番の人、26番の人と番号であれば名前を知らなくても呼び出せますね。
C言語を使うと自分の足を誤って撃ち抜いてしまうことがある。 C++を使えばそのような間違いを犯しにくくなる。しかし、やってしまったときには足全体が無くなる。

ISLe
記事: 2645
登録日時: 9年前
連絡を取る:

Re: ポインタを理解する

#4

投稿記事 by ISLe » 6年前

どこぞの古いハード絡みの経験だけに沿って書かれた解説に毒されていますね。

処理系依存ですしnバイト分の領域なんていちいち型から実際のサイズに変換する必要ないですよ。
領域の大きさは宣言された型の値を格納するのに十分な大きさです。
ごく当たり前のことなのでわざわざ書く必要もないと思います。

int a;
int* b;
両方とも宣言された型の値を格納する記憶域を持つ変数を宣言していて、変数aも変数bも値の読み書きの動作自体に違いはありません。

重要なのは値が持つ型の違いだけです。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: ポインタを理解する

#5

投稿記事 by softya(ソフト屋) » 6年前

書き添えます。
ISLeさんの言われるとおりなので、図を書く時は仮想アドレスは0x1000,0x2000とかグンと離れた値を書いておいてください。
これならサイズを気にしなくて良いですから。

と言うことで改訂版。
int* b; // メモリ上にint*型の領域を確保し、その領域の名前をbとする。この変数はポインタ型である。
って感じでしょうか。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ISLe
記事: 2645
登録日時: 9年前
連絡を取る:

Re: ポインタを理解する

#6

投稿記事 by ISLe » 6年前

ポインタがどのように使うものでどのように便利なのかというのは、ときにポインタそのものの理解の邪魔になると思います。
ポインタそのものを理解しなくても、使用する場面ごとのパターンを覚えるという使い方をしているひとも数多存在します。

3D_3Dさんが以前書かれた日記と同じ展開にならないとよいですが。

Rittai_3D
記事: 524
登録日時: 7年前

Re: ポインタを理解する

#7

投稿記事 by Rittai_3D » 6年前

>>softya様

返信ありがとうございます。
softya(ソフト屋) さんが書きました:まず、
int* b; // メモリ上に4バイト分の領域を確保し、領域の名前をbとする。この変数はポインタ型である。
って感じですかね。

それぞれ図を書いてみてはどうでしょうか? 型 変数名 仮のアドレス(0x1000など) 値 を記載してください。
① 2行目、3行目の状態。値は不定と書いてください。
② 4行目、5行目の状態。出来ればbとaの関係も矢印でお願いします。

【補足】
ちなみにポインタが4バイトかは環境依存です。
2バイトや8バイトもあります。64bitOSだと8バイトですね。
わかりました。ペイントで頑張って描きます。

ポインタは環境依存だったのですか…いままで決まってるものだと思っていました。
初心者です

Rittai_3D
記事: 524
登録日時: 7年前

Re: ポインタを理解する

#8

投稿記事 by Rittai_3D » 6年前

>>KORYUOH様

返信ありがとうございます。
KORYUOH さんが書きました:概念でよく言われるのが名簿の関係です
宣言と名簿
int a; ○○さん
int* b; xx番の人

という考え方です。

aさんとかbさんとかだと名前を知っていないと呼び出せませんが、
10番の人、26番の人と番号であれば名前を知らなくても呼び出せますね。
この考え方は今まで聞いたことがなかったですが、わかりやすいです。

ポインタが理解出来るように頑張ります
初心者です

Rittai_3D
記事: 524
登録日時: 7年前

Re: ポインタを理解する

#9

投稿記事 by Rittai_3D » 6年前

>>ISLe様

返信ありがとうございます。
ISLe さんが書きました:どこぞの古いハード絡みの経験だけに沿って書かれた解説に毒されていますね。

処理系依存ですしnバイト分の領域なんていちいち型から実際のサイズに変換する必要ないですよ。
領域の大きさは宣言された型の値を格納するのに十分な大きさです。
ごく当たり前のことなのでわざわざ書く必要もないと思います。

int a;
int* b;
両方とも宣言された型の値を格納する記憶域を持つ変数を宣言していて、変数aも変数bも値の読み書きの動作自体に違いはありません。

重要なのは値が持つ型の違いだけです。
自分が参考にした資料は古かったようです。

バイト数は書く必要がない!のですね。

>重要なのは値が持つ型の違いだけです。

int,charとの違いということですか?
初心者です

Rittai_3D
記事: 524
登録日時: 7年前

Re: ポインタを理解する

#10

投稿記事 by Rittai_3D » 6年前

>>softya様

返信ありがとうございます。
softya(ソフト屋) さんが書きました:書き添えます。
ISLeさんの言われるとおりなので、図を書く時は仮想アドレスは0x1000,0x2000とかグンと離れた値を書いておいてください。
これならサイズを気にしなくて良いですから。

と言うことで改訂版。
int* b; // メモリ上にint*型の領域を確保し、その領域の名前をbとする。この変数はポインタ型である。
って感じでしょうか。
わかりました。画像にはそのように書きます。

ただ、投稿は午後になります。少し用事がありまして。
初心者です

Rittai_3D
記事: 524
登録日時: 7年前

Re: ポインタを理解する

#11

投稿記事 by Rittai_3D » 6年前

>>ISLe様

返信ありがとうございます。
ISLe さんが書きました:ポインタがどのように使うものでどのように便利なのかというのは、ときにポインタそのものの理解の邪魔になると思います。
ポインタそのものを理解しなくても、使用する場面ごとのパターンを覚えるという使い方をしているひとも数多存在します。

3D_3Dさんが以前書かれた日記と同じ展開にならないとよいですが。
>ポインタがどのように使うものでどのように便利なのかというのは、ときにポインタそのものの理解の邪魔になると思います。

自分はいつもこれを考えています。もしかして、自分がポインタを理解できない理由はこれを考えているからでしょうかね。

>ポインタそのものを理解しなくても、使用する場面ごとのパターンを覚えるという使い方をしているひとも数多存在します。

これが一番驚いた事です。理解せずにパターンで覚える人が存在するんですね。

そのパターンとは何でしょうか?ファイルオープンの
FILE* fp;
みたいなものでしょうか。
初心者です

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: ポインタを理解する

#12

投稿記事 by softya(ソフト屋) » 6年前

そういえば、5つの回答に5回返答しなくても良いですよ。実質3人ですし。

【補足】ISLeさんのは、中々出来ないんだったら方法を変えてたら?って提案だと思います。
数学の公式を覚えろってのに近い感じかなぁ。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

珈琲

Re: ポインタを理解する

#13

投稿記事 by 珈琲 » 6年前

私はMMOのオンラインゲームをやっていたので、「スキルスロットみたいなものだ」と言われて納得できました。(同時にポリモーフィズムも)
スキルウィンドウにスキルの実体があって、ショートカットキー(スキルスロット)にセットすると、そこから呼び出せる
この一連の流れはそのまま
int abc; //スキルの実体の宣言
int* s;  //ショートカットキーの宣言
s=&abc; //ショートカットキーに設定
*s     //ショートカット呼び出し
     

まぁポインタのこの手の喩え話はいくらでもあるので参考にならないかもしれませんが・・・

Rittai_3D
記事: 524
登録日時: 7年前

Re: ポインタを理解する

#14

投稿記事 by Rittai_3D » 6年前

ただいま戻りました。

画像を貼っておきますので、間違えてる部分などを教えてください。
添付ファイル
4-5.png
4-5.png (13.24 KiB) 閲覧数: 4812 回
2-3.png
2-3.png (9.88 KiB) 閲覧数: 4812 回
初心者です

Rittai_3D
記事: 524
登録日時: 7年前

Re: ポインタを理解する

#15

投稿記事 by Rittai_3D » 6年前

>>珈琲様

返信ありがとうございます。
珈琲 さんが書きました:私はMMOのオンラインゲームをやっていたので、「スキルスロットみたいなものだ」と言われて納得できました。(同時にポリモーフィズムも)
スキルウィンドウにスキルの実体があって、ショートカットキー(スキルスロット)にセットすると、そこから呼び出せる
この一連の流れはそのまま
int abc; //スキルの実体の宣言
int* s;  //ショートカットキーの宣言
s=&abc; //ショートカットキーに設定
*s     //ショートカット呼び出し
     

まぁポインタのこの手の喩え話はいくらでもあるので参考にならないかもしれませんが・・・
MMOオンラインゲーム...?自分はゲームをあまりしないのでわかりません...。

好きなものの例えは分かりやすいかもしれませんね。
初心者です

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: ポインタを理解する

#16

投稿記事 by softya(ソフト屋) » 6年前

2-3.png の内容の書き換えて矢印を書き加えるだけで4-5は完成します。
なので、必要なのはaとbの値を書き換えるだけなのです。
難しく考え過ぎと思えます。

あとデバッガでよく見てなかったというのも言えるかもしれません。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Rittai_3D
記事: 524
登録日時: 7年前

Re: ポインタを理解する

#17

投稿記事 by Rittai_3D » 6年前

>>softya様

返信ありがとうございます。
softya(ソフト屋) さんが書きました:2-3.png の内容の書き換えて矢印を書き加えるだけで4-5は完成します。
なので、必要なのはaとbの値を書き換えるだけなのです。
難しく考え過ぎと思えます。

あとデバッガでよく見てなかったというのも言えるかもしれません。
書き換えてみました。これでどうですか?

また、デバッガで見落としも有るかも知れないので明日確認してみます。(10:00以降はPC使用禁止ですので)
添付ファイル
4-5-1.png
4-5-1.png (13.56 KiB) 閲覧数: 4732 回
初心者です

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: ポインタを理解する

#18

投稿記事 by softya(ソフト屋) » 6年前

なにかうまく伝わっていない・・・。

値が不定のままって事はないです。両方共代入なので値が代入されます。
あと矢印は一旦忘れてください。余計混乱させていると思いました。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

かずま

Re: ポインタを理解する

#19

投稿記事 by かずま » 6年前

理解していない人に図を書いてくださいというのは、無茶なことで、
理解している人が図を描いて示すほうがずっと教育的なことだと、
私は思います。これは、課題の丸投げに解答を示すのとは異なります。

コード:

#include <stdio.h>

int main(void)
{
    int a;
    int *b;
    a = 6;
    printf(" a = %d\n", a);
    printf("&a = %p\n", &a);
    b = &a;
    printf(" b = %p\n", b);
    printf("&b = %p\n", &b);
    printf("*b = %d\n", *b);
    return 0;
}
私のところでの実行結果

コード:

 a = 6
&a = 0047FD08
 b = 0047FD08
&b = 0047FD04
*b = 6
実際に表示されるアドレスは、コンパイラにより上記とは異なります。

int a; と int *b; で a と b を宣言したときのメモリ

コード:

           +------------+
0x0047fd04 |    不定    | b
           +------------+
0x0047fd08 |    不定    | a
           +------------+
a = 6; を実行したときのメモリ

コード:

           +------------+
0x0047fd04 |    不定    | b
           +------------+
0x0047fd08 |      6     | a
           +------------+
b = &b; を実行したときのメモリ

コード:

           +------------+
0x0047fd04 | 0x0047fd08 | b
           +------------+
0x0047fd08 |      6     | a
           +------------+
アドレスの値は問題ではなく、次の図を描けばよい

コード:

           +------------+
0x0047fd04 |     +------------+  b
           +------------+     |
0x0047fd08 |      6     |<----+  a
           +------------+

かずま

Re: ポインタを理解する

#20

投稿記事 by かずま » 6年前

ちょっと訂正。
アドレスの値は問題ではなく、次の図を描けばよい

コード:

b +----------+      a +-----------+
  |     +------------>|     6     |
  +----------+        +-----------+

珈琲

Re: ポインタを理解する

#21

投稿記事 by 珈琲 » 6年前

横からで度々失礼しますが、
勝手ですが最初はショートカットという認識でいいんじゃないでしょうか

画像
windowsのデスクトップに並ぶショートカットファイルのイメージです。
ショートカットファイルはどんな種類でも、ファイルパスを指すだけなので、ファイル自体の容量は非常に少ないです。

ファイルパスを設定すればその先に設置してあるファイルにアクセスできるわけです。

int File;//ファイル
int* Shortcut = &File;//ファイルパスを設定

Rittai_3D
記事: 524
登録日時: 7年前

Re: ポインタを理解する

#22

投稿記事 by Rittai_3D » 6年前

>>かずま様

返信ありがとうございます。
かずま さんが書きました:理解していない人に図を書いてくださいというのは、無茶なことで、
理解している人が図を描いて示すほうがずっと教育的なことだと、
私は思います。これは、課題の丸投げに解答を示すのとは異なります。

コード:

#include <stdio.h>

int main(void)
{
int a;
int *b;
a = 6;
printf(" a = %d\n", a);
printf("&a = %p\n", &a);
b = &a;
printf(" b = %p\n", b);
printf("&b = %p\n", &b);
printf("*b = %d\n", *b);
return 0;
}
私のところでの実行結果

コード:

a = 6
&a = 0047FD08
b = 0047FD08
&b = 0047FD04
*b = 6
実際に表示されるアドレスは、コンパイラにより上記とは異なります。

int a; と int *b; で a と b を宣言したときのメモリ

コード:

+------------+
0x0047fd04 | 不定 | b
+------------+
0x0047fd08 | 不定 | a
+------------+
a = 6; を実行したときのメモリ

コード:

+------------+
0x0047fd04 | 不定 | b
+------------+
0x0047fd08 | 6 | a
+------------+
b = &b; を実行したときのメモリ

コード:

+------------+
0x0047fd04 | 0x0047fd08 | b
+------------+
0x0047fd08 | 6 | a
+------------+
アドレスの値は問題ではなく、次の図を描けばよい

コード:

+------------+
0x0047fd04 | +------------+ b
+------------+ |
0x0047fd08 | 6 |<----+ a
+------------+
かずま さんが書きました:ちょっと訂正。
アドレスの値は問題ではなく、次の図を描けばよい

コード:

b +----------+ a +-----------+
| +------------>| 6 |
+----------+ +-----------+
図を書いて下さりありがとうございます。とてもわかりやすかったです。

さらに質問ですが、アドレスが代入されるとはどういう意味でしょうか?

a=6 とするとaの領域に6が代入されますが、 b= &a は bの領域にaのアドレス( 0x0047fd08 )が代入されるとは b = 0x0047fd08 と言う意味ですか?
初心者です

Rittai_3D
記事: 524
登録日時: 7年前

Re: ポインタを理解する

#23

投稿記事 by Rittai_3D » 6年前

>>珈琲様

返信ありがとうございます。
珈琲 さんが書きました:横からで度々失礼しますが、
勝手ですが最初はショートカットという認識でいいんじゃないでしょうか

画像
windowsのデスクトップに並ぶショートカットファイルのイメージです。
ショートカットファイルはどんな種類でも、ファイルパスを指すだけなので、ファイル自体の容量は非常に少ないです。

ファイルパスを設定すればその先に設置してあるファイルにアクセスできるわけです。

int File;//ファイル
int* Shortcut = &File;//ファイルパスを設定
うーん、よくわからないです...

File が c:\windows\system32\cmd.exe だとすると、 Shortcut はどうなるのですか?
初心者です

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: ポインタを理解する

#24

投稿記事 by softya(ソフト屋) » 6年前

分かった気がするが一番危険なので気をつけてくださいね。

>a=6 とするとaの領域に6が代入されますが、 b= &a は bの領域にaのアドレス( 0x0047fd08 )が代入されるとは b = 0x0047fd08 と言う意味ですか?

はい。代入ですから。これだけ見れば単純ですよ。

【補足】
ポインタ値を代入する時はとても単純です。
これを参照したりする時にいろんな機能・効果が出てきます。
ただ、ここで理解すべきことはポインタ変数に入っているはポインタ値と言うただの数値であると言う一点です。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Lawliet
記事: 12
登録日時: 6年前

Re: ポインタを理解する

#25

投稿記事 by Lawliet » 6年前

いろいろな方たちが説明してくれていますが
それぞれに異なった方針を持っている人もいますので、ごちゃごちゃしてしまう場合は
違う方の説明を聞くときはほかの方の説明を半分ぐらい忘れた状態で聞くといいと思います。
(わからないことが残っても一旦理解したらそのあと質問すればいいので)

文法の面からひとこと言わせてもらいます。
「宣言の時」と「そうじゃない時」を分けて考えるとわかりやすいかもしれません

コード:

////////////////////////////////
//宣言の時

int *p;	//宣言の時は'*'を付ける

////////////////////////////////
//そうじゃない時

/*アドレスを示す状態*/
p;	//代入されたアドレスを示します

int x;
p = &x;	//アドレスを代入することができます。pの指すアドレスが変わります

/*値を示す状態*/
*p;	//pで示しているアドレスの変数の中身を示す

*p = 10;	//pの型の対応する値代入できます。pの指すアドレスの先の変数の値が変わります。

////////////////////////////////
//アドレスを求める演算子

//'&'を付けるときはその変数のアドレスがほしいとき、
//例えばアドレスを代入したい時など

p = &x;
わかりにくかったかもしれませんが結局何が言いたいかというと
  • ポインタ変数の宣言のときは                  *を付ける
  • ポインタ変数の示すアドレスを示すときは           何もつけない
  • ポインタ変数の指すアドレスにある変数の値を示すとき   *を付ける
  • その変数自体のアドレスを示すときは             &を付ける
これらをしっかりと区別してほしいということです。

Rittai_3D
記事: 524
登録日時: 7年前

Re: ポインタを理解する

#26

投稿記事 by Rittai_3D » 6年前

>>softya様

返信ありがとうございます。
softya(ソフト屋) さんが書きました:分かった気がするが一番危険なので気をつけてくださいね。

>a=6 とするとaの領域に6が代入されますが、 b= &a は bの領域にaのアドレス( 0x0047fd08 )が代入されるとは b = 0x0047fd08 と言う意味ですか?

はい。代入ですから。これだけ見れば単純ですよ。

【補足】
ポインタ値を代入する時はとても単純です。
これを参照したりする時にいろんな機能・効果が出てきます。
ただ、ここで理解すべきことはポインタ変数に入っているはポインタ値と言うただの数値であると言う一点です。
つまり、普通の変数とほぼ同じで、入っている値の違い、という事ですか?
初心者です

Rittai_3D
記事: 524
登録日時: 7年前

Re: ポインタを理解する

#27

投稿記事 by Rittai_3D » 6年前

>>Lawliet様

返信ありがとうございます。
Lawliet さんが書きました:いろいろな方たちが説明してくれていますが
それぞれに異なった方針を持っている人もいますので、ごちゃごちゃしてしまう場合は
違う方の説明を聞くときはほかの方の説明を半分ぐらい忘れた状態で聞くといいと思います。
(わからないことが残っても一旦理解したらそのあと質問すればいいので)

文法の面からひとこと言わせてもらいます。
「宣言の時」と「そうじゃない時」を分けて考えるとわかりやすいかもしれません

コード:

////////////////////////////////
//宣言の時

int *p; //宣言の時は'*'を付ける

////////////////////////////////
//そうじゃない時

/*アドレスを示す状態*/
p; //代入されたアドレスを示します

int x;
p = &x; //アドレスを代入することができます。pの指すアドレスが変わります

/*値を示す状態*/
*p; //pで示しているアドレスの変数の中身を示す

*p = 10; //pの型の対応する値代入できます。pの指すアドレスの先の変数の値が変わります。

////////////////////////////////
//アドレスを求める演算子

//'&'を付けるときはその変数のアドレスがほしいとき、
//例えばアドレスを代入したい時など

p = &x;
わかりにくかったかもしれませんが結局何が言いたいかというと
  • ポインタ変数の宣言のときは                  *を付ける
  • ポインタ変数の示すアドレスを示すときは           何もつけない
  • ポインタ変数の指すアドレスにある変数の値を示すとき   *を付ける
  • その変数自体のアドレスを示すときは             &を付ける
これらをしっかりと区別してほしいということです。
何となくわかったような気がしますが、softya様のおっしゃる通り「分かった気がするが一番危険」なのでしっかり理解していきたいです。
初心者です

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: ポインタを理解する

#28

投稿記事 by softya(ソフト屋) » 6年前

3D_3D さんが書きました:つまり、普通の変数とほぼ同じで、入っている値の違い、という事ですか?
値の違いとも言えません。
int型とint*型にメモリ上は同じ値が入っていても参照するときの動作が違うからです。
なので整数型とポインタ型による動作の違いは参照時の動作の違いです。

例えば0x1000と言う値の場合、int a=0x1000;なら16進数で0x1000で10進数で4096です。
int *b=0x1000;なら0x1000がポインタ値となるのでint c = *b;と書けば0x1000番地に書かれてるメモリの内容をint型として参照してint型のcに代入します。
0x1000(仮想アドレス)がint x=100;であるなら、cには100が入ります。

※ パソコンの場合、アドレスは自動で決まるのでこんな決め打ちはできません。あくまでシミュレーションです。

【補足】
かずまさんが書いたことで逆に混乱しそうなsので補足しておきます。
int *b=(int *)0x1000;
と書かないとC言語の文法エラー出ます。でも言いたいことは文法じゃなく値の意味なので省略しました。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ISLe
記事: 2645
登録日時: 9年前
連絡を取る:

Re: ポインタを理解する

#29

投稿記事 by ISLe » 6年前

見事に日記のコメント欄と同じ展開ですね。

ポインタ型の変数に値が格納されるイメージを図にしてもらう段階で、ポインタが何をどうやって指すかというイメージは先行し過ぎじゃないかと思うのですが。

ポインタの機能重視で、使い方で覚えろという意見が圧倒的多数なので、パターンで覚えるのも良いかもしれません。
新しいパターンに出会うたびに苦労されるかもしれませんが。
最後に編集したユーザー ISLe on 2013年8月06日(火) 18:30 [ 編集 2 回目 ]

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: ポインタを理解する

#30

投稿記事 by softya(ソフト屋) » 6年前

ISLe さんが書きました:見事に日記のコメント欄と同じ展開ですね。

ポインタ型の変数に値が格納されるイメージを図にしてもらう段階で、ポインタが何をどうやって指すかというイメージは先行し過ぎじゃないかと思うのですが。

ポインタの機能重視で、使い方で覚えろという意見が圧倒的多数なので、パターンで覚えるのも良いかもしれません。
新しいパターンに出会うたびに苦労されるかもしれませんが。
そっちに切り替えましょうか。3D_3Dさんも混乱されているようですし。
【補足】 決めるのは3D_3Dさんなので、方針変更されても問題ないですよとだけ言っておきます。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ISLe
記事: 2645
登録日時: 9年前
連絡を取る:

Re: ポインタを理解する

#31

投稿記事 by ISLe » 6年前

int型の変数の記憶域には、int型の値を格納でき、変数名で記憶域にアクセスできる。
int*型の変数の記憶域には、int*型の値を格納でき、変数名で記憶域にアクセスできる。
まず理解してもらいたいのはこれだけのことなんですけどね。

かずま

Re: ポインタを理解する

#32

投稿記事 by かずま » 6年前

3D_3D さんが書きました: 図を書いて下さりありがとうございます。とてもわかりやすかったです。

さらに質問ですが、アドレスが代入されるとはどういう意味でしょうか?
とてもわかりにくかったようですね。
「b = &b; を実行したときのメモリ」と書いてしまいましたが、
「b = &a; を実行したときのメモリ」の間違いだということは理解されていますよね。
不定だった b のメモリが、a のアドレスに変わりましたよね。
これが、「アドレスが代入される」という意味です。

「a = 6; を実行したときのメモリ」のところでは、
不定だった a のメモリが、6 という値に変わりましたよね。
これが、「6 が代入される」という意味です。
3D_3D さんが書きました: a=6 とするとaの領域に6が代入されますが、 b= &a は bの領域にaのアドレス( 0x0047fd08 )が代入されるとは b = 0x0047fd08 と言う意味ですか?
いいえ、違います。

次のプログラムを Cコンパイラでコンパイルすると、警告メッセーが出るはずです。
C++コンパイラだと、エラーメッセージが出ます。

コード:

#include <stdio.h>
 
int main(void)
{
    int *b;
    b = 0x0047fd08;
    return 0;
}
b の型は、int * です。0x0047fd08 の型は、int です。
型が異なるから、コンパイラは文句を言ってくるのです。

b = &a; の場合、b の型は、int * です。&a の型も、int * です。
同じだから、代入できるのです。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: ポインタを理解する

#33

投稿記事 by softya(ソフト屋) » 6年前

色んな人が書くことで逆に3D_3Dさんを困らせている気がするので私はしばらくだまります。
出来るだけ誰か一人の方針に絞って説明をして、それをフォローする形で進めてください。
3D_3Dさんが理解する筋道を作る事が最優先だと考えます。

【補足】
それならこれが良いと案がないのが私が黙る理由です。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
三郎
記事: 17
登録日時: 8年前

Re: ポインタを理解する

#34

投稿記事 by 三郎 » 6年前

横から口を挟んで申し訳ありませんが皆さんの議論を見ていますと考えさせられます。
私はソフトに関して(他の事も)ド素人でポインターの事はよく分かりません。
だから使いません。
しかし参考になるソフト(ソースリスト)、考え方を自分のソフトに書き加えるような場合、ポインターの部分を、まる写しにして加えています。
このようにしてコンパイラーのエラーが出なければ、また作成したソフトが可笑しな動きをしていなければそれで良しとして、逃げています。
これは自分の作ったソフトが自分で使うだけの代物で、他人に見せたり、それほど高性能な機能を必要としないからです。

そこで皆さんに質問しますが、
私の認識(勝手な認識、多分間違っているかも)

1.ポインターを使ってもアプリの実行速度は、さほど速くならない?。
2.ポインターを使ってもメモリー等の節約にさほど貢献しない?貢献してもメモリ等の単価が下がっている昨今あまり重要ではない?。
3.ポインターを使うとアプリのソースがスマートに書ける?。ソースリストの拡張性、汎用性が向上する、そして作業の能率が向上する。
4.ポインタを苦労して理解さえすれば、分かりやすいソースが書ける。ソースコードも小さくなる。
5.ポインターを理解していなければ計算機の学校を卒業できず、ソフト技術者として、生活していけない。


このような事なのかなと思っていますが、ポインターを使うメリットは何でしょうか?

無理して使う必要があるのでしょうか?
もし 1.項の実行速度が上がるなら無理して勉強して、使ってみたく思います宜しくお願いします。

アバター
へにっくす
記事: 628
登録日時: 7年前
住所: 東京都

Re: ポインタを理解する

#35

投稿記事 by へにっくす » 6年前

三郎 さんが書きました:横から口を挟んで申し訳ありませんが皆さんの議論を見ていますと考えさせられます。
別トピックとしてあげてほしいかも。とりあえず、
三郎 さんが書きました:無理して使う必要があるのでしょうか?
に関してだけ。無理して使う必要はありません。何かしら代替となるようなモノで逃げられるなら、それで構わないです。
ただその都度いちいち結果優先でコーディングするということは、思った通りの結果になるまで、何度も試行錯誤することになります。
ポインターに限らず、基本というか仕組みを理解しておけば、結果を想定してコーディングするだけなので、時間をとられずに済みます。
理解しておくと言うのは大事なことですよ。
written by へにっくす

アバター
へにっくす
記事: 628
登録日時: 7年前
住所: 東京都

Re: ポインタを理解する

#36

投稿記事 by へにっくす » 6年前

うーん…ここまで白熱するとは思いませんでした
で、何だか出尽くした雰囲気が出てるので、前のトピック(http://dixq.net/forum/viewtopic.php?f=3&t=13591)の、
Player_Initで、&playerならokだがplayer_t *player;にしたときplayerだとうまくいかない理由の答えをちらっと述べます。

まずポインタの概念は、入れる箱を用意するという感じ。
int a = 0;
int型の変数でこれは実体を示している
int *p = NULL;
int型の実体の場所を示す変数。
なので実体の場所を示す変数に場所でないものを入れるのはおかしい。だから
int *p = 0x1000;
というのはダメで、
int *p = (int*)0x1000;
というふうにキャスト変換しないといけない。
&をつけるとつけられた変数のアドレスを返すので
int *p = &a;
これは事実、存在するアドレスを代入してますよね。ここまでは大丈夫かな?
なので前のトピックの
struct player_t player;
Player_Init(&player);
はok。
では
struct player_t *player;
としたときは
Player_Init(player);
としますがこれって実体があることが保証されてますかね?
されていないですよね。すくなくとも、Player_Initに渡す前に、
playerに実体のある変数のアドレスを渡さなければなりません。

これがうまくいかない理由だと思いますがどうでしょう?
オフトピック
この独り言が一番近かったので、関数の受け渡し方と述べたのですけどね。。
3D_3D さんが書きました:思いついたのは
・どのアドレスに割り振られるかわからないうちに初期化されるから、かなと思いました。
written by へにっくす

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: ポインタを理解する

#37

投稿記事 by softya(ソフト屋) » 6年前

今後どの勉強方法で行くのかは、3D_3Dさんに決めていただきたいと思います。
なので、とりあえず3D_3Dさんの意見を待ちたいです。

【補足】
私はCASL2アセンブラで根本から理解するという道も検討しておりました。
遠回りなんですけどね。

【補足追記】
> 三郎さんへ
別トピックにして頂けると嬉しいです。

カンタン解説:ポインタは大抵は配列の添字で代用可能です。
ただ、配列の添字をポインタ代わりに置き換えを考えれる人はポインタも理解できると思います。

ポインタが必須なのは大きな領域を動的確保するとぐらいでしょうか。
それとポインタが高速性を発揮するのは、ソートなどの分野です。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Ryo

Re: ポインタを理解する

#38

投稿記事 by Ryo » 6年前

こんなイメージでも

int a; // 家a

int *p; // 住所録p(新品)

p = &a; // 住所録pに、家aの"住所"を書き込む

a = 310; // 家aにサトーさんが住む

*p= 310; // 住所録pにかかれた住所(=家a)にサトーさんが住む

p = 123; // 住所録pにヒフミさんを住まわせようとして怒られる

p = (int*)123; // 住所録pに"1-2-3"という"住所"を書き込む


//関数引き渡し (Func(char*))
char a; // 家aを建てる
Func( &a ); // aの住所をFuncさんに渡して、結果を送ってもらったりする

char *p; // 新品の住所録
Func( p ); // 新品の住所録の白紙の部分をさして、Funcさんに、この住所に結果を送れと無理を言う


//メモリ確保
int *p,*p2; // 住所録pとp2

p = new int; // 家を建てて、住所録にその住所を書く

p2 = new int[10]; // 10部屋あるアパートを立てる

p2[3] = 510; // 3号室にゴトーさんが住む

p2++; // アパートを一部屋一部屋みていく
// char型の小さなアパートでも、LONGLONGな大きな部屋の億ションでも、一部屋ずつ

delete p; // 住所録に書かれた家を壊す(壊したあとに家に人を住まわせようとすると怒られる)
delete[] p2;    // 集合住宅破壊用

p= NULL; // 住所録に消しゴムをかけて住所を消しておく

かずま

Re: ポインタを理解する

#39

投稿記事 by かずま » 6年前

三郎 さんが書きました: このような事なのかなと思っていますが、ポインターを使うメリットは何でしょうか?
ポインタを使わないと、ファイル操作も、文字列操作もできません。
コマンドライン引数も使えません。
画像データも扱えません。

printf は、int printf(const char *format, ...);
(C99 からは * に restrict がつきますが) と宣言されていて、
第1引数にポインタを要求します。

配列は、暗黙のうちにポインタに変換されて要素にアクセスします。
a は、*(a + i) のことなんです。

関数は、暗黙のうちにポインタに変換されて関数を呼び出します。
printf("hoge") は、(&printf)("hoge") のことなんです。

ポインタを使わずに実用的なプログラムを書くのは不可能です。

Rittai_3D
記事: 524
登録日時: 7年前

Re: ポインタを理解する

#40

投稿記事 by Rittai_3D » 6年前

すいません、部活で返信ができませんでした。

>>へにっくす様

返信ありがとうございます。
へにっくす さんが書きました:うーん…ここまで白熱するとは思いませんでした
で、何だか出尽くした雰囲気が出てるので、前のトピック(http://dixq.net/forum/viewtopic.php?f=3&t=13591)の、
Player_Initで、&playerならokだがplayer_t *player;にしたときplayerだとうまくいかない理由の答えをちらっと述べます。

まずポインタの概念は、入れる箱を用意するという感じ。
int a = 0;
int型の変数でこれは実体を示している
int *p = NULL;
int型の実体の場所を示す変数。
なので実体の場所を示す変数に場所でないものを入れるのはおかしい。だから
int *p = 0x1000;
というのはダメで、
int *p = (int*)0x1000;
というふうにキャスト変換しないといけない。
&をつけるとつけられた変数のアドレスを返すので
int *p = &a;
これは事実、存在するアドレスを代入してますよね。ここまでは大丈夫かな?
なので前のトピックの
struct player_t player;
Player_Init(&player);
はok。
では
struct player_t *player;
としたときは
Player_Init(player);
としますがこれって実体があることが保証されてますかね?
されていないですよね。すくなくとも、Player_Initに渡す前に、
playerに実体のある変数のアドレスを渡さなければなりません。

これがうまくいかない理由だと思いますがどうでしょう?
オフトピック
この独り言が一番近かったので、関数の受け渡し方と述べたのですけどね。。
3D_3D さんが書きました:思いついたのは
・どのアドレスに割り振られるかわからないうちに初期化されるから、かなと思いました。
なるほど。実体があることが保証されてないからエラーが出たのですか。ということは「構造体の実体があることが保証されていないうちに初期化処理をしようとしてエラー落ちしてしまう」ということでしょうか?
初心者です

Rittai_3D
記事: 524
登録日時: 7年前

Re: ポインタを理解する

#41

投稿記事 by Rittai_3D » 6年前

>>softya様

返信ありがとうございます。
softya(ソフト屋) さんが書きました:今後どの勉強方法で行くのかは、3D_3Dさんに決めていただきたいと思います。
なので、とりあえず3D_3Dさんの意見を待ちたいです。

【補足】
私はCASL2アセンブラで根本から理解するという道も検討しておりました。
遠回りなんですけどね。
自分としては、もうすこし勉強して、どうしても理解できないようならばパターンで覚えようと考えております。

今はもう少しポインタを勉強したいと思います。
初心者です

Rittai_3D
記事: 524
登録日時: 7年前

Re: ポインタを理解する

#42

投稿記事 by Rittai_3D » 6年前

>>Ryo様

返信ありがとうございます。
Ryo さんが書きました:こんなイメージでも

コード:

int a; // 家a

int *p; // 住所録p(新品)

p = &a; // 住所録pに、家aの"住所"を書き込む

a = 310; // 家aにサトーさんが住む

*p= 310; // 住所録pにかかれた住所(=家a)にサトーさんが住む

p = 123; // 住所録pにヒフミさんを住まわせようとして怒られる

p = (int*)123; // 住所録pに"1-2-3"という"住所"を書き込む


//関数引き渡し (Func(char*))
char a; // 家aを建てる
Func( &a ); // aの住所をFuncさんに渡して、結果を送ってもらったりする

char *p; // 新品の住所録
Func( p ); // 新品の住所録の白紙の部分をさして、Funcさんに、この住所に結果を送れと無理を言う


//メモリ確保
int *p,*p2; // 住所録pとp2

p = new int; // 家を建てて、住所録にその住所を書く

p2 = new int[10]; // 10部屋あるアパートを立てる

p2[3] = 510; // 3号室にゴトーさんが住む

p2++; // アパートを一部屋一部屋みていく
// char型の小さなアパートでも、LONGLONGな大きな部屋の億ションでも、一部屋ずつ

delete p; // 住所録に書かれた家を壊す(壊したあとに家に人を住まわせようとすると怒られる)
delete[] p2;    // 集合住宅破壊用

p= NULL; // 住所録に消しゴムをかけて住所を消しておく
イメージがしやすく、分かりやすかったです。newもmalloc()でも同じように扱えると思いますのでやってみます。
初心者です

アバター
三郎
記事: 17
登録日時: 8年前

Re: ポインタを理解する

#43

投稿記事 by 三郎 » 6年前

へにっくすさん返信ありがとうございました。
確かに貴方の言われるように、
「ただその都度いちいち結果優先でコーディングするということは、思った通りの結果になるまで、何度も試行錯誤することになります。
ポインターに限らず、基本というか仕組みを理解しておけば、結果を想定してコーディングするだけなので、時間をとられずに済みます。
理解しておくと言うのは大事なことですよ。」
言われてみればその通りです。分かっているけど中々実行できないものですね、そして私の場合もし理解できても少し経つと忘れてしまうのです(年齢からくる?)
肝に銘じやってみます。

かずまさん、返信ありがとうございました。
私は配列までは、何とか少し分かっていますので、これから勉強すれば、かずまさんの言われる事が少しは理解できるかも分かりません。
有難うございました。


ソフト屋さん私に対する配慮有難うございます。
ポインターの必要理由が理解できない人が非常に多い事が分かり、ネット検索してみましたら次のサイトが見つかりました。
http://d.hatena.ne.jp/kura-replace/20120616/1339856279
ここに書いてある事を読んでみましたら如何に私が無知であったかが分かりました。
レベルの高いプログラムを目指すなら避けて通れないように感じました。

可能な限り勉強してソースを掲示板に張れるようになったら再度教えてほしいと思います。
それまでは皆さんの書かれている物を読ませてもらいます。
有難うございました、お騒がせしました。

ISLe
記事: 2645
登録日時: 9年前
連絡を取る:

Re: ポインタを理解する

#44

投稿記事 by ISLe » 6年前

3D_3Dさんが理解できていない部分と重なるので書いておきます。

ポインタは、アドレス値を複製し代入して使うので、関数の仮引数と同じく、実行時に与えられた値で動作します。

なので、手を加えることなく将来にわたって利用可能なプログラムを書くことができます。

OSが、リリースされたときには存在しなかった未知のアプリケーションソフトを動かせるのもポインタがあるからです。

アバター
へにっくす
記事: 628
登録日時: 7年前
住所: 東京都

Re: ポインタを理解する

#45

投稿記事 by へにっくす » 6年前

3D_3D さんが書きました:なるほど。実体があることが保証されてないからエラーが出たのですか。ということは「構造体の実体があることが保証されていないうちに初期化処理をしようとしてエラー落ちしてしまう」ということでしょうか?
そういうことです。
ポインタを宣言するということは、場所(アドレス)を示すだけで、実体を示しているわけではないことにご注意くださいね。
written by へにっくす

Rittai_3D
記事: 524
登録日時: 7年前

Re: ポインタを理解する

#46

投稿記事 by Rittai_3D » 6年前

すいません。様々な理由がありまして、返信できませんでした。

>>へにっくす様

返信ありがとうございます。
へにっくす さんが書きました:
3D_3D さんが書きました:なるほど。実体があることが保証されてないからエラーが出たのですか。ということは「構造体の実体があることが保証されていないうちに初期化処理をしようとしてエラー落ちしてしまう」ということでしょうか?
そういうことです。
ポインタを宣言するということは、場所(アドレス)を示すだけで、実体を示しているわけではないことにご注意くださいね。
わかりました。実体でなくポインタを示すのですね。
初心者です

Lawliet
記事: 12
登録日時: 6年前

Re: ポインタを理解する

#47

投稿記事 by Lawliet » 6年前

>3D_3Dさん

なんだか回答の対応ばかりで受け身になってしまったような気がします。
なのでソフト屋さんも言いっているように方針を決めて状況を整理したほうがいいと思います。
3D_3D さんが書きました:
softya(ソフト屋) さんが書きました: 今後どの勉強方法で行くのかは、3D_3Dさんに決めていただきたいと思います。
なので、とりあえず3D_3Dさんの意見を待ちたいです。

【補足】
私はCASL2アセンブラで根本から理解するという道も検討しておりました。
遠回りなんですけどね。
自分としては、もうすこし勉強して、どうしても理解できないようならばパターンで覚えようと考えております。

今はもう少しポインタを勉強したいと思います。
この返信だけでは不十分な感じもします。
「どのように勉強していくか」を聞いているのに対し「もうすこし勉強して」と返信されているので、
「どのように」というのをしっかり明記した方がいいと思います。

もし決めることができないならばその旨を伝え、
このトピックスの最初のように今現在のポインタの理解度を示して
わからないところを一つづつやっていくというのもいい方法だと思います。

ISLe
記事: 2645
登録日時: 9年前
連絡を取る:

Re: ポインタを理解する

#48

投稿記事 by ISLe » 6年前

へにっくす さんが書きました:ポインタを宣言するということは、場所(アドレス)を示すだけで、実体を示しているわけではないことにご注意くださいね。
ポインタ型の変数を宣言すると、場所を示す値を格納する領域が確保されますが、その値が具体的な場所を示しているとは限りません。

特定のオブジェクトが持つアドレスをポインタと呼びますが、その場合のポインタはそのオブジェクトを指すもの(値)です。
オブジェクトは常に記憶域を持つので、場所を示すが実体を示さないという状況はありません。

アバター
へにっくす
記事: 628
登録日時: 7年前
住所: 東京都

Re: ポインタを理解する

#49

投稿記事 by へにっくす » 6年前

3D_3D さんが書きました:わかりました。実体でなくポインタを示すのですね。
えっと、、上記を言いかえると、ポインタを宣言するということは、実体でなくポインタを示すとなっちゃいますけど?(^^;
ポインタを宣言するということは、実体でなく場所を示す、ですよ。
ISLe さんが書きました:ポインタ型の変数を宣言すると、場所を示す値を格納する領域が確保されますが、その値が具体的な場所を示しているとは限りません。
これがよりしっくりくる。フォローありがとうございます。
ポインタを宣言する、ではなくポインタ型の変数を宣言すると、ですね。

よくポインタ型の変数はNULLで初期化してるけど、これなんかは具体的な場所でないことを示すために使ってますよね
変数の場所(アドレス)はNULLになることがないので(Cの規約でしたっけ?間違ってたらすみません)。
ISLe さんが書きました:特定のオブジェクトが持つアドレスをポインタと呼びますが、その場合のポインタはそのオブジェクトを指すもの(値)です。
オブジェクトは常に記憶域を持つので、場所を示すが実体を示さないという状況はありません。
ポインタについての説明ですね。
ポインタ型の変数についてとは別ですね?
「ポインタを宣言する」とは言わない方がよさそうですね。ごっちゃになってる(^^;

私も言葉でうまく説明できていないあたり、何だか危ないですかね。。。
written by へにっくす

Rittai_3D
記事: 524
登録日時: 7年前

Re: ポインタを理解する

#50

投稿記事 by Rittai_3D » 6年前

インターネットに繋がりにくいところに居るので返信ができませんでした。

>>Lawliet様

返信ありがとうございます。
Lawliet さんが書きました:>3D_3Dさん

なんだか回答の対応ばかりで受け身になってしまったような気がします。
なのでソフト屋さんも言いっているように方針を決めて状況を整理したほうがいいと思います。
3D_3D さんが書きました:
softya(ソフト屋) さんが書きました: 今後どの勉強方法で行くのかは、3D_3Dさんに決めていただきたいと思います。
なので、とりあえず3D_3Dさんの意見を待ちたいです。

【補足】
私はCASL2アセンブラで根本から理解するという道も検討しておりました。
遠回りなんですけどね。
自分としては、もうすこし勉強して、どうしても理解できないようならばパターンで覚えようと考えております。

今はもう少しポインタを勉強したいと思います。
この返信だけでは不十分な感じもします。
「どのように勉強していくか」を聞いているのに対し「もうすこし勉強して」と返信されているので、
「どのように」というのをしっかり明記した方がいいと思います。

もし決めることができないならばその旨を伝え、
このトピックスの最初のように今現在のポインタの理解度を示して
わからないところを一つづつやっていくというのもいい方法だと思います。
ありがとうございます。まだ自分で方針が決められないのでおっしゃる通りに一つ一つ疑問を解決していくようにしたいと思います。
初心者です

ISLe
記事: 2645
登録日時: 9年前
連絡を取る:

Re: ポインタを理解する

#51

投稿記事 by ISLe » 6年前

誤った刷り込みが行われるパターン。

コード:

void hoge(int *p);
int i = 10; 
int *p; /* ポインタを宣言します  */
p = &i; /* ポインタに代入します */
*p = 20; /* ポインタが指す変数を書き換えできます */
hoge(p); /* ポインタを渡します */
&iの意味がスルーされポインタを渡すという部分だけが記憶に残りがち。

丁寧に説明するとこんな感じ。

コード:

void hoge(int *p);
int i = 10; 
int *p; /* intへのポインタ型の変数を宣言します  */
p = &i; /* 変数pに、int型の変数iのアドレス(intへのポインタ型の値)を代入します */
*p = 20; /* 変数iのアドレス(変数pに格納されている値)に間接演算子が働くことで変数iの記憶域に対して代入が行われます */
hoge(p); /* 変数iのアドレス(変数pに格納されている値)をコピーして、intへのポインタ型の仮引数に渡します */
ちなみにきちんと理解せず区別できないままだとこんなことに。

コード:

void hoge(int *p);
int i = 10; 
int *p; /* ポインタを宣言します  */
p = &i; /* ポインタにポインタを代入します */
*p = 20; /* ポインタが指す変数を書き換えできます */
hoge(p); /* ポインタをポインタに渡します */
変数の宣言と間接参照の組み合わせを元にして覚えていると思われる。



ヌルポインタはあらゆるオブジェクトの持つアドレスと比較して等しくないことが保証される値です。
それとは別に、初期化されていない一時変数の値は未規定です。

Rittai_3D
記事: 524
登録日時: 7年前

Re: ポインタを理解する

#52

投稿記事 by Rittai_3D » 6年前

>>へにっくす様

返信ありがとうございます。
へにっくす さんが書きました:
3D_3D さんが書きました:わかりました。実体でなくポインタを示すのですね。
えっと、、上記を言いかえると、ポインタを宣言するということは、実体でなくポインタを示すとなっちゃいますけど?(^^;
ポインタを宣言するということは、実体でなく場所を示す、ですよ。
ISLe さんが書きました:ポインタ型の変数を宣言すると、場所を示す値を格納する領域が確保されますが、その値が具体的な場所を示しているとは限りません。
これがよりしっくりくる。フォローありがとうございます。
ポインタを宣言する、ではなくポインタ型の変数を宣言すると、ですね。

よくポインタ型の変数はNULLで初期化してるけど、これなんかは具体的な場所でないことを示すために使ってますよね
変数の場所(アドレス)はNULLになることがないので(Cの規約でしたっけ?間違ってたらすみません)。
ISLe さんが書きました:特定のオブジェクトが持つアドレスをポインタと呼びますが、その場合のポインタはそのオブジェクトを指すもの(値)です。
オブジェクトは常に記憶域を持つので、場所を示すが実体を示さないという状況はありません。
ポインタについての説明ですね。
ポインタ型の変数についてとは別ですね?
「ポインタを宣言する」とは言わない方がよさそうですね。ごっちゃになってる(^^;

私も言葉でうまく説明できていないあたり、何だか危ないですかね。。。
何か勘違いしていたようです。アドレスと実体をごちゃ混ぜにしてしまいました。
初心者です

Rittai_3D
記事: 524
登録日時: 7年前

Re: ポインタを理解する

#53

投稿記事 by Rittai_3D » 6年前

いままでポインタを勉強していて、自分には理解できないと思いました。ですので、ポインタを理解するのではなく、パターンで覚えたいと思います。

自分がポインタを理解できるように解説して下さった皆様には本当に悪いと思います。しかし、ポインタを理解するよりもパターンで覚えた方が早いと考えました。

ですので、方針を変えまして、これからはパターンで覚えたいと思います。

身勝手なことを申し上げてしまい、申し訳ありません。
初心者です

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: ポインタを理解する

#54

投稿記事 by softya(ソフト屋) » 6年前

パターン法ですが話が進まないみたいので、3D_3Dさんがこういうことをやりたい!とパターンを提示したほうが良いかもしれませんね。
関数に構造体ポインタを渡して関数先で構造体を書き換えたいとか、関数から構造体のポインタを持ち帰りたいとか、関数に配列を渡したいとかね。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Rittai_3D
記事: 524
登録日時: 7年前

Re: ポインタを理解する

#55

投稿記事 by Rittai_3D » 6年前

>>softya様

返信ありがとうございます。
softya(ソフト屋) さんが書きました:パターン法ですが話が進まないみたいので、3D_3Dさんがこういうことをやりたい!とパターンを提示したほうが良いかもしれませんね。
関数に構造体ポインタを渡して関数先で構造体を書き換えたいとか、関数から構造体のポインタを持ち帰りたいとか、関数に配列を渡したいとかね。
シューティングなどのゲームだけでなく、他のことにも使えるように「どのような時にポインタを使うか」を教えていただきたいです。
初心者です

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: ポインタを理解する

#56

投稿記事 by softya(ソフト屋) » 6年前

ポインタに関してならアプリでもゲームでも大抵は関係ないです。
ただ、どのパターンを覚えると良いかはパターンで覚えたことがないので私には難しいです。
この状況にはどうしたらよいですか?って事なら答えられるんですが。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Rittai_3D
記事: 524
登録日時: 7年前

Re: ポインタを理解する

#57

投稿記事 by Rittai_3D » 6年前

>>softya様

返信ありがとうございます。
softya(ソフト屋) さんが書きました:ポインタに関してならアプリでもゲームでも大抵は関係ないです。
ただ、どのパターンを覚えると良いかはパターンで覚えたことがないので私には難しいです。
この状況にはどうしたらよいですか?って事なら答えられるんですが。
それでは、その都度聞くのはダメでしょうか?
初心者です

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: ポインタを理解する

#58

投稿記事 by softya(ソフト屋) » 6年前

疑問に疑問で返しますが、どうなんでしょうか?
パターン暗記法の効能がよく分かっていない私です。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
へにっくす
記事: 628
登録日時: 7年前
住所: 東京都

Re: ポインタを理解する

#59

投稿記事 by へにっくす » 6年前

3D_3D さんが書きました:それでは、その都度聞くのはダメでしょうか?
それがパターンを覚えるってことだと思いますけど。
だから、結果優先でやるということは、思い通りの結果を得るまで試行錯誤することになる、と言いました。

なのでこのトピックの主旨から外れると思いますので、ここはいったん解決にした方がいいかもしれません。
【追記】私が言うことではない気がしたので、上の文言は取り消します。。
最後に編集したユーザー へにっくす on 2013年8月11日(日) 17:18 [ 編集 1 回目 ]
written by へにっくす

ISLe
記事: 2645
登録日時: 9年前
連絡を取る:

Re: ポインタを理解する

#60

投稿記事 by ISLe » 6年前

パターンで覚えるというのは、ポインタを要求されたときに答える形になるので、どんなときに使うかを考える必要はありません。
なので、パターンで覚えることができても、自ら積極的にポインタを使うことにはほとんど貢献しません。


アドレス演算子(&)を付けると型に*が1個増える
間接演算子(*)を付けると型から*が1個減る
*の数を揃えて使う
というのが基本パターンですね。


例えば自作の関数にポインタを使いたかったら、とりあえず引数の型をポインタにしてしまい、*の数が揃うように適当にコーディングするといった感じになりますね。

たいちう
記事: 418
登録日時: 9年前

Re: ポインタを理解する

#61

投稿記事 by たいちう » 6年前

元々のスレの趣旨は、こうですよね。

> と理解が曖昧です。このトピックでポインタを克服したいと思います。

何故ポインタを克服したいのかは書いていませんが、
上達したい、壁を超えたい、というのが目的ですよね?
前スレのテーマもオブジェクト指向でしたし。

私も「パターンとして覚える」というのは理解の放棄(延期)でしかないと思います。
また暫くしたら、似たようなスレを立てることになりそうじゃないですか?


3D_3Dさんは高校生のようですので、「ポインタ」を「微積分」に置き換えて考えてみましょう。
(私が高校生だったのも大昔だし、例えが変かもしれません)
パターンを覚えて数学の実力がアップすると思いますか?
逆に、理解なしで実力をアップさせるには、微積分のパターンをどれだけ覚えたらよいと思いますか?

JavaやC#ならポインタは無いので、言語を変更することで当面の問題はなくなります。
文系の大学を目指すことで微積分が必要無くなるようなものです。
ただ、JavaやC#でプログラミングをしても、ポインタ程度に理解しにくい概念は何度でも出てくるでしょう。
例えば、オブジェクト指向を使いこなすことは、ポインタを使いこなすよりもよほど難しいと思います。


このような本でじっくり勉強してはどうでしょうか?
C言語ポインタ完全制覇(当時は良い本だと思った)
詳解C言語 ポインタ完全攻略(読んだことない)
オフトピック
JavaやC#や文系大学をけなす意図は一切ありませんよ。念のため。

Rittai_3D
記事: 524
登録日時: 7年前

Re: ポインタを理解する

#62

投稿記事 by Rittai_3D » 6年前

>>softya様

返信ありがとうございます。
softya(ソフト屋) さんが書きました:疑問に疑問で返しますが、どうなんでしょうか?
パターン暗記法の効能がよく分かっていない私です。
ポインタを理解しないでプログラムが書けるから初心者の鬼門などと言われるポインタを意識しなくていい、などでしょうか?
オフトピック
実際、鬼門と呼ばれているかは知りませんが。
初心者です

Rittai_3D
記事: 524
登録日時: 7年前

Re: ポインタを理解する

#63

投稿記事 by Rittai_3D » 6年前

>>へにっくす様

返信ありがとうございます。
へにっくす さんが書きました:
3D_3D さんが書きました:それでは、その都度聞くのはダメでしょうか?
それがパターンを覚えるってことだと思いますけど。
だから、結果優先でやるということは、思い通りの結果を得るまで試行錯誤することになる、と言いました。

なのでこのトピックの主旨から外れると思いますので、ここはいったん解決にした方がいいかもしれません。
【追記】私が言うことではない気がしたので、上の文言は取り消します。。
なんだかんだで試行錯誤することが一番の近道みたいですね。早速明日からやってみたいと思います
初心者です

Rittai_3D
記事: 524
登録日時: 7年前

Re: ポインタを理解する

#64

投稿記事 by Rittai_3D » 6年前

>>たいちう様

返信ありがとうございます。
たいちう さんが書きました:元々のスレの趣旨は、こうですよね。

> と理解が曖昧です。このトピックでポインタを克服したいと思います。

何故ポインタを克服したいのかは書いていませんが、
上達したい、壁を超えたい、というのが目的ですよね?
前スレのテーマもオブジェクト指向でしたし。

私も「パターンとして覚える」というのは理解の放棄(延期)でしかないと思います。
また暫くしたら、似たようなスレを立てることになりそうじゃないですか?
3D_3Dさんは高校生のようですので、「ポインタ」を「微積分」に置き換えて考えてみましょう。
(私が高校生だったのも大昔だし、例えが変かもしれません)
パターンを覚えて数学の実力がアップすると思いますか?
逆に、理解なしで実力をアップさせるには、微積分のパターンをどれだけ覚えたらよいと思いますか?

JavaやC#ならポインタは無いので、言語を変更することで当面の問題はなくなります。
文系の大学を目指すことで微積分が必要無くなるようなものです。
ただ、JavaやC#でプログラミングをしても、ポインタ程度に理解しにくい概念は何度でも出てくるでしょう。
例えば、オブジェクト指向を使いこなすことは、ポインタを使いこなすよりもよほど難しいと思います。


このような本でじっくり勉強してはどうでしょうか?
C言語ポインタ完全制覇(当時は良い本だと思った)
詳解C言語 ポインタ完全攻略(読んだことない)
オフトピック
JavaやC#や文系大学をけなす意図は一切ありませんよ。念のため。
まだ微積分は習ってないので、別の物に脳内変換して考えました。
たしかに、パターンを覚えただけでは実力アップは出来ないですね。やはり理解しないと実力アップは望めないのですね。

JavaやC# はポインタが無いのには驚きです。どの言語にもあると思っていたので。
初心者です

たいちう
記事: 418
登録日時: 9年前

Re: ポインタを理解する

#65

投稿記事 by たいちう » 6年前

既に注意されているのかもしれませんが、全文引用は控えて下さい。
必要な部分のみの引用にして下さい。スレが無駄に長くなり読みにくくなります。
それと、まとめてレスを付けても良いのですよ。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: ポインタを理解する

#66

投稿記事 by softya(ソフト屋) » 6年前

また、みんなが色々言うと混乱するかもしれませんが、これを試してみませんか?
「Visualization C Interpreterのダウンロード : Vector ソフトを探す!」
http://www.vector.co.jp/soft/dl/win95/p ... 42764.html
バグが多いので、迂闊なことするとすぐ落ちますが簡単なプログラムなら通ると思います。
C言語の動作を映像的に表示しながら実行します。

自分でコードを書いて納得できるまで色々試してみてはどうでしょうか?
とりあえずのサンプル。付属のサンプルが難しそうだったので。

コード:

#include<stdio.h>
main(){
 int *p;
 int a;
 int b;
 p=&a;
 *p = 1;
 p=&b;
 *p = 2;
 printf("%d,%d",a,b);
}
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

かずま

Re: ポインタを理解する

#67

投稿記事 by かずま » 6年前

softya(ソフト屋) さんが書きました:また、みんなが色々言うと混乱するかもしれませんが、これを試してみませんか?
「Visualization C Interpreterのダウンロード : Vector ソフトを探す!」
わざわざ、そんなソフトをインストールする必要はないと思います。
次の図で理解できなければ、何をやっても無駄な気がします。

コード:

int *p;
  +----------+
p |  (int *) }
  +----------+

int a;
  +----------+       +-----------+ 
p |  (int *) |     a |   (int)   |
  +----------+       +-----------+ 

int b:
  +----------+       +-----------+         +-----------+
p |  (int *) |     a |   (int)   |       b |   (int)   |
  +----------+       +-----------+         +-----------+

p = &a;
  +----------+       +-----------+         +-----------+
p |   &a  *------> a |   (int)   |       b |   (int)   |
  +----------+       +-----------+         +-----------+

*p = 1;
  +----------+       +-----------+         +-----------+
p |   &a  *------> a |     1     |       b |   (int)   |
  +----------+       +-----------+         +-----------+

p = &b;         +-------------------+
  +----------+  |    +-----------+  |      +-----------+
p |   &b  *-----+  a |     1     |  +--> b |   (int)   |
  +----------+       +-----------+         +-----------+

*p = 2;         +-------------------+
  +----------+  |    +-----------+  |      +-----------+
p |   &b  *-----+  a |     1     |  +--> b |     2     |
  +----------+       +-----------+         +-----------+

アバター
へにっくす
記事: 628
登録日時: 7年前
住所: 東京都

Re: ポインタを理解する

#68

投稿記事 by へにっくす » 6年前

3D_3D さんが書きました:なんだかんだで試行錯誤することが一番の近道みたいですね。早速明日からやってみたいと思います
#私の後のISLeさんへのレスが無いみたいなので。
ISLeさんが基本パターンを挙げられているので、頭に入れておいた方がよいですよ。
written by へにっくす

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: ポインタを理解する

#69

投稿記事 by softya(ソフト屋) » 6年前

と、また3D_3Dさんが混乱しそうなので3D_3Dさんにどうするか決めて頂くまで、一旦だまります。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Rittai_3D
記事: 524
登録日時: 7年前

Re: ポインタを理解する

#70

投稿記事 by Rittai_3D » 6年前

すいません、夏風邪を引いたようで返信が出来ませんでした。

>>たいちう様

返信ありがとうございます。

>既に注意されているのかもしれませんが、全文引用は控えて下さい。
>必要な部分のみの引用にして下さい。スレが無駄に長くなり読みにくくなります。

すいません、以後気をつけます。
オフトピック
この位なら大丈夫ですよね?一応確認しておきたくて。
>>softya様

返信ありがとうございます。

>また、みんなが色々言うと混乱するかもしれませんが、これを試してみませんか?
>「Visualization C Interpreterのダウンロード : Vector ソフトを探す!」

すいません、現在親のPCを借りてプログラムを書いているので、あまりいじりすぎると怒られてしまうので、自分のPCが使えるようになったら試してみたいと思います。

>>かずま様

返信ありがとうございます。
かずま さんが書きました:

コード:

int *p;
  +----------+
p |  (int *) }
  +----------+
 
int a;
  +----------+       +-----------+ 
p |  (int *) |     a |   (int)   |
  +----------+       +-----------+ 
 
int b:
  +----------+       +-----------+         +-----------+
p |  (int *) |     a |   (int)   |       b |   (int)   |
  +----------+       +-----------+         +-----------+
 
p = &a;
  +----------+       +-----------+         +-----------+
p |   &a  *------> a |   (int)   |       b |   (int)   |
  +----------+       +-----------+         +-----------+
 
*p = 1;
  +----------+       +-----------+         +-----------+
p |   &a  *------> a |     1     |       b |   (int)   |
  +----------+       +-----------+         +-----------+
 
p = &b;         +-------------------+
  +----------+  |    +-----------+  |      +-----------+
p |   &b  *-----+  a |     1     |  +--> b |   (int)   |
  +----------+       +-----------+         +-----------+
 
*p = 2;         +-------------------+
  +----------+  |    +-----------+  |      +-----------+
p |   &b  *-----+  a |     1     |  +--> b |     2     |
  +----------+       +-----------+         +-----------+
ちょっと不安ですがなんとなくならわかります。p = &a がちょっと???状態です。
オフトピック
以降、返信は大体3人ずつ位で区切ります。
初心者です

Rittai_3D
記事: 524
登録日時: 7年前

Re: ポインタを理解する

#71

投稿記事 by Rittai_3D » 6年前

>>へにっくす様

返信ありがとうございます。
へにっくす さんが書きました: #私の後のISLeさんへのレスが無いみたいなので。
ISLeさんが基本パターンを挙げられているので、頭に入れておいた方がよいですよ。
すいません、ISLe様のレスを見落としていました。頭に入れておきます。

>>ISLe様

返信ありがとうございます。また、返信が遅れてしまい申し訳ありません。
ISLe さんが書きました:パターンで覚えるというのは、ポインタを要求されたときに答える形になるので、どんなときに使うかを考える必要はありません。
なので、パターンで覚えることができても、自ら積極的にポインタを使うことにはほとんど貢献しません。
なるほど。ただ、自分の様な初心者が無闇にポインタは使わない方が良いと思うので、ポインタが理解できない初心者にはいいと思います。
ISLe さんが書きました: アドレス演算子(&)を付けると型に*が1個増える
間接演算子(*)を付けると型から*が1個減る
*の数を揃えて使う
を頭に入れてしまいます。
初心者です

Rittai_3D
記事: 524
登録日時: 7年前

Re: ポインタを理解する

#72

投稿記事 by Rittai_3D » 6年前

考えがコロコロ変わってしまいますが、たいちう様の

>「パターンとして覚える」というのは理解の放棄(延期)でしかないと思います。

で、やはりパターンではなく、ポインタを理解しようと考えました。

自分は、ソースコード中にポインタが出たときに「なぜここでポインタを使うのか?」で詰まってしまいます。

例えば、龍神録プログラミングの館のここ

コード:

//引数1と引数2のうち大きい方を引数1に代入する
void input_pad_or_key(int *p, int k){
        *p = *p>k ? *p : k;
}
で何故ポインタを引数に?で今は詰まります。( 最初の頃はそういうもの で誤魔化してました )
オフトピック
自分はそこさえ分かれば理解出来そうな気がします、と考えました
初心者です

アバター
Tatu
記事: 445
登録日時: 9年前
住所: 北海道

Re: ポインタを理解する

#73

投稿記事 by Tatu » 6年前

pを書き換えたいからポインタを使用しているのではないでしょうか?

それとも

コード:

int input_pad_or_key(int p,int k){
	return p>k ? p :k;
}

pad=input_pad_or_key(pad,key);
でもいいんじゃないかということですか?

Rittai_3D
記事: 524
登録日時: 7年前

Re: ポインタを理解する

#74

投稿記事 by Rittai_3D » 6年前

>>Tatu様

返信ありがとうございます。

>pを書き換えたいからポインタを使用しているのではないでしょうか?

書き換えるのにポインタを使う必要が分からないです。
Tatu さんが書きました:

コード:

int input_pad_or_key(int p,int k){
	return p>k ? p :k;
}
pad=input_pad_or_key(pad,key);
でもいいのでは?ということです。
初心者です

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: ポインタを理解する

#75

投稿記事 by softya(ソフト屋) » 6年前

別にTaruさんの方法でも問題がないなら構わないんですよ。人により、
(1) *p = *p>k ? *p : k;
(2) return p>k ? p :k;
(1)と(2)のどちらが素直か意見が別れそうですが。

そうですね。同じ動作であるということは理解されていますよね。
(1)と(2)のそれぞれの動作を説明してみてください。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Rittai_3D
記事: 524
登録日時: 7年前

Re: ポインタを理解する

#76

投稿記事 by Rittai_3D » 6年前

>>softya様

返信ありがとうございます。

>(1) *p = *p>k ? *p : k;
>(2) return p>k ? p :k;
>(1)と(2)のそれぞれの動作を説明してみてください。

(1)がわかりません。*pに*pかkの大きい方を代入する?ですか?
(2)はpとkで大きい方を返す

でしょうかね。
初心者です

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: ポインタを理解する

#77

投稿記事 by softya(ソフト屋) » 6年前

そうですね。
じゃあ、(1)の*pと(2)のpって何が違うんでしょうか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

かずま

Re: ポインタを理解する

#78

投稿記事 by かずま » 6年前

ポインタを使う方の関数の呼び出し

コード:

    input_pad_or_key(&pad.key[configpad.left], CheckStateKey(KEY_INPUT_LEFT));
ポインタを使わない方の関数の呼び出し

コード:

    pad.key[configpad.left] = input_pad_or_key(pad.key[configpad.left], CheckStateKey(KEY_INPUT_LEFT));
どっちの方がいいですか?

Rittai_3D
記事: 524
登録日時: 7年前

Re: ポインタを理解する

#79

投稿記事 by Rittai_3D » 6年前

>>softya様

返信ありがとうございます。

>(1)の*pと(2)のpって何が違うんでしょうか?

(1)はパッドの番号のポインタ?よくわかりません。

(2)はパッドの番号を表す、でしょうか?

>>かずま様

返信ありがとうございます。

>ポインタを使う方の関数の呼び出し
>input_pad_or_key(&pad.key[configpad.left], CheckStateKey(KEY_INPUT_LEFT));
>ポインタを使わない方の関数の呼び出し
>pad.key[configpad.left]=input_pad_or_key(pad.key[configpad.left],CheckStateKey(KEY_INPUT_LEFT));
>どっちの方がいいですか?

ポインタの方がわかりやすく、楽に書けるということでしょうか?
初心者です

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: ポインタを理解する

#80

投稿記事 by softya(ソフト屋) » 6年前

「パッドの番号」って事はコード自体が理解できていない気がして来ましたが保留しておきますか? 本筋と違うんですが大きく間違っています。
つまり、ポインタの前にこのコードの機能自体を把握できていないって事ですけど。

コード:

//引数1と引数2のうち大きい方を引数1に代入する
void input_pad_or_key(int *p, int k){
        *p = *p>k ? *p : k;
}
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

かずま

Re: ポインタを理解する

#81

投稿記事 by かずま » 6年前

3D_3D さんが書きました: ポインタの方がわかりやすく、楽に書けるということでしょうか?
違います。

関数を呼び出すというのは、ある処理を任せる、仕事を委託するということです。

ポインタを使った関数 input_pad_or_key は、「ある変数の値と、もう一つの値を比較
して、大きいほうの値を最初の変数に代入する」という仕事をやり遂げることができます。

ところが、ポインタを使わないほうの関数は、「ある値と、もう一つの値を比較して
大きいほうを返す」という仕事しかしていません。
関数の呼び出し側、すなわち仕事を委託したほうは、返された値を、最初の値を
持っていた変数に代入するという仕事を自分でやらなければなりません。

せっかく関数を用意して、仕事をやってもらうんだったら、代入操作もその関数に
やってもらいたいですよね。

ポインタを使わないと、関数は引数として「値」しかもらえませんから、それらを
比較して大きいほうの値がわかっても、それをどの「変数」に代入すれば
いいのか分かりません。
関数の中の p は、
呼び出し側の pad.key[configpad.left] という変数の「値」であって、
pad.key[configpad.left] という「変数」ではありません。

ポインタを使ったほうの関数は、最初の変数の場所をもらっているので、そこから
値を読みだすこともできるし、比較結果の大きいほうの値をその変数に代入すること
ができます。
関数の中の *p は
呼び出し側の pad.key[configpad.left] という変数そのものなのです。

input_pad_or_key(&pad.key[configpad.left], CheckStateKey(KEY_INPUT_LEFT));
という呼び出しの &pad.key[configpad.left] は
pad.key[configpad.left] という変数の場所(アドレス) をポインタとして
input_pad_or_key に渡しています。

一方
pad.key[configpad.left] = input_pad_or_key(pad.key[configpad.left], CheckStateKey(KEY_INPUT_LEFT));
という呼び出しの pad.key[configpad.left] は
pad.key[configpad.left] という変数の値を int として
input_pad_or_key に渡しています。

ポインタが何のためにあるのか、これでもわかりませんか?

Rittai_3D
記事: 524
登録日時: 7年前

Re: ポインタを理解する

#82

投稿記事 by Rittai_3D » 6年前

>>softya様

返信ありがとうございます。

>「パッドの番号」って事はコード自体が理解できていない気がして来ましたが保留しておきますか? 本筋と違うんですが大きく間違っています。
>つまり、ポインタの前にこのコードの機能自体を把握できていないって事ですけど。

何か勘違いしていたようです。もう一度書きます。

(1)パッドかキーボードの入力されているパッドのアドレスかキーコードを返す?#追記 返す ではなく、 *pに代入 です。
(2)パッドかキーボードの入力されているキーの値?を返す?

でしょうか?

>>かずま様

返信ありがとうございます。

>ポインタを使ったほうの関数は、最初の変数の場所をもらっているので、そこから
値を読みだすこともできるし、比較結果の大きいほうの値をその変数に代入すること
ができます。
>関数の中の *p は
>呼び出し側の pad.key[configpad.left] という変数そのものなのです。

そのような意味だったのですか!理解できました。ポインタが如何に便利かわかりました。

つまり、「pのアドレスにpad.key[configpad.left]のアドレスかキーコードを渡す」ということですか?文章力がなくて何を言っているかわからないと思いますが、何とか理解出来たと思います。少し不安ですが。
最後に編集したユーザー Rittai_3D on 2013年8月16日(金) 00:40 [ 編集 1 回目 ]
初心者です

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: ポインタを理解する

#83

投稿記事 by softya(ソフト屋) » 6年前

> (1)パッドかキーボードの入力されているパッドのアドレスかキーコードを返す?
> (2)パッドかキーボードの入力されているキーの値?を返す?
それも違いますね。キーの値でもないですし、キーコードでもないです。ましてやアドレスでもありません。
pad.key[configpad.left]に入っている値そのものを分かっていない感じです。
それと(1)と(2)はある一点を除いては同じ動作をするので、アドレスなんて言葉は出てこないです。
かずまさんの説明を理解しているなら書けるはずなんですよ。

> つまり、「pのアドレスにpad.key[configpad.left]のアドレスかキーコードを渡す」ということですか?
これも不安ですね。アドレスかキーコードだと2つはだいぶ違うものです。

【補足】
なんだろうシンプルな話なのに、逆に複雑に考えてしまっている気がしてなりません。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Rittai_3D
記事: 524
登録日時: 7年前

Re: ポインタを理解する

#84

投稿記事 by Rittai_3D » 6年前

>>softya様

返信ありがとうございます。

>それも違いますね。キーの値でもないですし、キーコードでもないです。ましてやアドレスでもありません。
>pad.key[configpad.left]に入っている値そのものを分かっていない感じです。
>それと(1)と(2)はある一点を除いては同じ動作をするので、アドレスなんて言葉は出てこないです。

値を返すかpのポインタに代入するか、ですか?

>かずまさんの説明を理解しているなら書けるはずなんですよ。

自分の文章力が乏しいため上手くかけません。頭の中ではこういうことか!とわかったつもりでも、いい言葉が思いつかないというか、何というか…

>なんだろうシンプルな話なのに、逆に複雑に考えてしまっている気がしてなりません

まさにその通りです。
初心者です

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: ポインタを理解する

#85

投稿記事 by softya(ソフト屋) » 6年前

例えを思いついたので、書いてみます。
ルール。[誤解を生みそうなので修正]
・箱が3つあります。
・箱には、それぞれ1と2と3と言う番号が書いてあります。
・箱には数字を書いた紙を入れられます。
・箱にはラベルに英数字で名前を付けられます。
・箱には数値型とポインタ型と言う属性札が付けれます。
・ポインタ型は箱に入れらた紙に書かれた数値の番号の箱を参照できるようになります。これを間接参照と呼びます。
例として間接参照でポインタ属性の箱を覗くと2と書かれた紙が入っていたら、箱2を使えって意味となります。

作業。
・箱1にaと言う名前をつけました。属性は数値型です。
・紙に5と書いて箱aに入れました。
・箱2にbと言う名前をつけました。属性は数値型です。
・紙に13と書いて箱bに入れました。
・箱3にpと言う名前をつけました。属性はポインタ型です。
・紙に1と書いて箱pに入れました。

質問。
・上記の作業後に箱pを間接参照した場合には、なんて書かれた紙を取り出すことに成るでしょうか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

どぶろく
記事: 75
登録日時: 7年前

Re: ポインタを理解する

#86

投稿記事 by どぶろく » 6年前

softya様、いつもおせわになっております。
横から口をはさんで申し訳ないのですが、私の考えでは、

int* b;

という宣言があったら2つの変数が宣言されたと考えます。

b // アドレスを入れる変数
*b // 普通のint型の変数

ただし普通の変数である *b にはまだ領域が確保されていません。
なので b に他で確保されている領域のアドレスを代入する必要があります。
b にアドレスが代入されると、その領域を *b として使うことができます。

ISLe
記事: 2645
登録日時: 9年前
連絡を取る:

Re: ポインタを理解する

#87

投稿記事 by ISLe » 6年前

文章力が無いのならなおさら、文章自体を省略せずに書くべきだと思います。
誰も、簡潔に著せ、とは書いてないですよね。

コード:

void input_pad_or_key(int *p, int k){
        *p = *p>k ? *p : k;
}
上記の場合、intへのポインタ型の変数pに格納されたアドレスが指す記憶域に代入してます。

コード:

int input_pad_or_key(int p,int k){
    p = p>k ? p :k;
    return p;
}
上記の場合、int型の変数pの記憶域に代入してます。

3D_3Dさんの日記のコメントに、繰り返し唱えてって書いたことですけど、もう唱えるのやめてしまったのでしょうか。

たいちう
記事: 418
登録日時: 9年前

Re: ポインタを理解する

#88

投稿記事 by たいちう » 6年前

> 文章力が無いのならなおさら、文章自体を省略せずに書くべきだと思います。
> 誰も、簡潔に著せ、とは書いてないですよね。

文章力≒理解力なんですよね。
文章力を鍛えたら、理解力も向上しますよ。
上手く説明できないことは理解していないものと認識してください。
安易に理解したつもりにならないように。

一応ここでいう文章力は、文学作品やベストセラーを書けるような能力ではなく、
書き手の伝えたいことが読み手に伝わるような文章を書ける能力です。
文学的ではなく論理的な文章ですね。

かずま

Re: ポインタを理解する

#89

投稿記事 by かずま » 6年前

文章が書けなくても図は描けるようになりましたか?

次のプログラムで、*q = x - y; を実行した後のすべての変数
(main の a, b, c, d と sum_diff の x, y, p, r) の関係を
図に書いてみてください。

コード:

#include <stdio.h>

void sum_diff(int x, int y, int *p, int *q)
{
    *p = x + y;
    *q = x - y;
}

int main(void)
{
    int a = 23, b = 45, c, d;
    sum_diff(a, b, &c, &d);
    printf("a + b = %d\n", c);
    printf("a - b = %d\n", d);
    return 0;
}
実行結果

コード:

a + b = 68
a - b = -22

かずま

Re: ポインタを理解する

#90

投稿記事 by かずま » 6年前

どぶろく さんが書きました: int* b;

という宣言があったら2つの変数が宣言されたと考えます。

b // アドレスを入れる変数
*b // 普通のint型の変数

ただし普通の変数である *b にはまだ領域が確保されていません。
なので b に他で確保されている領域のアドレスを代入する必要があります。
b にアドレスが代入されると、その領域を *b として使うことができます。
int *b;
b = malloc(sizeof(int) * 3);

b にアドレスが代入され、
*b は b[0] として使うとことができますが、
*(b+1) すなわち b[1]、*(b+2) すわなち b[2] も使えます。
ということは、b と合わせて 4つの変数が「宣言された」
と考えるのですか?

どぶろく
記事: 75
登録日時: 7年前

Re: ポインタを理解する

#91

投稿記事 by どぶろく » 6年前

かずま様、いいことを言ってくれました。
まさに、かずま様の書いたことを理解できればいいのです。
次の段階として配列とポインタが同じように使えるということを理解できればいいと思います。

Rittai_3D
記事: 524
登録日時: 7年前

Re: ポインタを理解する

#92

投稿記事 by Rittai_3D » 6年前

個人的な事で返信が遅れてしまいました。皆様、回答ありがとうございます。

>>softya様

返信ありがとうございます。

>質問。
>・上記の作業後に箱pを間接参照した場合には、なんて書かれた紙を取り出すことに成るでしょうか?

箱aの5でしょうか?間接参照がよくわからないです。

>>ISLe様

返信ありがとうございます。

>文章力が無いのならなおさら、文章自体を省略せずに書くべきだと思います。
>誰も、簡潔に著せ、とは書いてないですよね。

そうでしたね。失礼しました。
ISLe さんが書きました:

コード:

void input_pad_or_key(int *p, int k){
        *p = *p>k ? *p : k;
}
上記の場合、intへのポインタ型の変数pに格納されたアドレスが指す記憶域に代入してます。
なぜintへのポインタ変数pに代入しているのでしょうか?ここもよくわかりません。

>3D_3Dさんの日記のコメントに、繰り返し唱えてって書いたことですけど、もう唱えるのやめてしまったのでしょうか。

わかったつもりになっていてやめてしまいました。また唱え直します。
初心者です

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: ポインタを理解する

#93

投稿記事 by softya(ソフト屋) » 6年前

> 箱aの5でしょうか?間接参照がよくわからないです。

箱のなかの紙を見て、そこに書かれている番号の箱を使うと言うことです。
箱を1つ経由する事が間接参照となります。
例えば子どもたちが遊びで使うとしても、難しいルールじゃないですよね?
箱を開けて中にある番号を書いた紙の番号を見て、その番号の別の箱を手に取るだけですから。

※ 答えが合っているかはわざと回答していません。
【補足】自信を持って、これこれこういう理由でxxです。とお答えください。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Rittai_3D
記事: 524
登録日時: 7年前

Re: ポインタを理解する

#94

投稿記事 by Rittai_3D » 6年前

>>かずま様

返信ありがとうございます。
かずま さんが書きました:文章が書けなくても図は描けるようになりましたか?
次のプログラムで、*q = x - y; を実行した後のすべての変数
(main の a, b, c, d と sum_diff の x, y, p, r) の関係を
図に書いてみてください。
申し訳ないのですが、投稿しようとした時に作成した画像データが消えてしまいました。もうしばらく待っていただけないでしょうか?

>>どぶろく様

返信ありがとうございます。

>かずま様、いいことを言ってくれました。
>まさに、かずま様の書いたことを理解できればいいのです。
>次の段階として配列とポインタが同じように使えるということを理解できればいいと思います。

配列とポインタは同じように扱えるのは知っていましたが、なぜがポインタの方がうまく理解出来ないです。配列はスラスラわかったしのですが。
初心者です

ISLe
記事: 2645
登録日時: 9年前
連絡を取る:

Re: ポインタを理解する

#95

投稿記事 by ISLe » 6年前

3D_3D さんが書きました:
ISLe さんが書きました:

コード:

void input_pad_or_key(int *p, int k){
        *p = *p>k ? *p : k;
}
上記の場合、intへのポインタ型の変数pに格納されたアドレスが指す記憶域に代入してます。
なぜintへのポインタ変数pに代入しているのでしょうか?ここもよくわかりません。
変数pに代入してはいませんよ。

仮引数の内容は、実引数で与えられた値のコピーです。
それはポインタ型であろうとなかろうと同じです。
3D_3D さんが書きました:>3D_3Dさんの日記のコメントに、繰り返し唱えてって書いたことですけど、もう唱えるのやめてしまったのでしょうか。
わかったつもりになっていてやめてしまいました。また唱え直します。
唱えるというのは書かれたことを読むというのではなくて、コーディングしているときに(ポインタ型に限らず)変数名を打鍵する都度、記憶域を確保していることや記憶域を参照していること、およびそこに格納された値を意識するということですよ。

int a = 10;
int *p = &a;
変数aの記憶域にあるのは何ですか
変数pの記憶域にあるのは何ですか

Rittai_3D
記事: 524
登録日時: 7年前

Re: ポインタを理解する

#96

投稿記事 by Rittai_3D » 6年前

>>softya様

返信ありがとうございます

>箱のなかの紙を見て、そこに書かれている番号の箱を使うと言うことです。
>箱を1つ経由する事が間接参照となります。

なるほど、そういう意味でしたか。わかりやすい返信ありがとうございます。

>※ 答えが合っているかはわざと回答していません。
>【補足】自信を持って、これこれこういう理由でxxです。とお答えください。

ポインタ型の箱pの中の紙に書かれている数が1なので、箱1の数、即ち5となります。


>>ISLe様

返信ありがとうございます。

>変数pに代入してはいませんよ。
>仮引数の内容は、実引数で与えられた値のコピーです。
>それはポインタ型であろうとなかろうと同じです。

やっと意味がわかりました。ずーっと前からの疑問が解決しました。

>唱えるというのは書かれたことを読むというのではなくて、コーディングしているときに(ポインタ型に限らず)変数名を打鍵する都度、記憶域を確保していることや記憶域を参照していること、およびそこに格納された値を意識するということですよ。

コメントを頂いた時から勘違いをしていました。恥ずかしいです。

>int a = 10;
>int *p = &a;
>変数aの記憶域にあるのは何ですか
>変数pの記憶域にあるのは何ですか

aの記憶域にあるのは10で、pの記憶域にある物はa訂正:の ですアドレスだと思います
最後に編集したユーザー Rittai_3D on 2013年8月19日(月) 06:07 [ 編集 1 回目 ]

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: ポインタを理解する

#97

投稿記事 by softya(ソフト屋) » 6年前

> ポインタ型の箱pの中の紙に書かれている数が1なので、箱1の数、即ち5となります。

そうです。その通りです。
ポインタってそういう物なんですがイメージ掴めませんかね?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ISLe
記事: 2645
登録日時: 9年前
連絡を取る:

Re: ポインタを理解する

#98

投稿記事 by ISLe » 6年前

ブレイクスルーできたのでしょうかね。
3D_3D さんが書きました:>int a = 10;
>int *p = &a;
>変数aの記憶域にあるのは何ですか
>変数pの記憶域にあるのは何ですか

aの記憶域にあるのは10で、pの記憶域にある物はa訂正:の ですアドレスだと思います
情報の不足はありますが、回答としては正解です。
ポインタ型の変数は、アドレスをやりとりするものだということを頭に刻み付けてください。

Rittai_3D
記事: 524
登録日時: 7年前

Re: ポインタを理解する

#99

投稿記事 by Rittai_3D » 6年前

返信が遅れてしまいまして申し訳ありません

>>softya様

返信ありがとうございます。

>そうです。その通りです。
>ポインタってそういう物なんですがイメージ掴めませんかね?

なんとなくイメージできましたが、まだ何か引っかかるというかなんというか...

>>ISLe様

返信ありがとうございます

>ブレイクスルーできたのでしょうかね

あと少しなんですが、その少しが大変です。

>情報の不足はありますが、回答としては正解です。
>ポインタ型の変数は、アドレスをやりとりするものだということを頭に刻み付けてください。

分かりました。あれで大体はあっていたのですね。
初心者です

Rittai_3D
記事: 524
登録日時: 7年前

Re: ポインタを理解する

#100

投稿記事 by Rittai_3D » 6年前

ポインタを完全に理解した訳ではありませんが、6〜7割程度は理解できました。

ですので、解決とさせて頂きます。ありがとうございました。

ポインタはじっくり勉強して完全に理解して行きたいと思います。早く理解しようと急ぎすぎました。
初心者です

閉鎖

“C言語何でも質問掲示板” へ戻る