ID非公開

2021/2/26 19:57

1111回答

C言語なんかでよく「ポインタがわからない」といわれます。これって、どの辺がわからないのでしょうか。

補足

多くの方にご協力いただきありがとうございます。 ここまで挙げられたものをまとめてみると、概ね次の3点になるかと思います。 (1) ソースコード上の「*」の意味は、実は文脈に応じて複数の異なる意味になるのに、単一の意味によって解釈しようとして混乱する。 (2) 変数の値が、整数値のアドレスで指定されるメモリ上に、型に応じたバイト数で記憶されるという、アーキテクチャについての知識がない。 (3) 変数とは異なる、ポインタならではの使い道を知らない。 私は8ビットパソコンの時代に触り始めたので、特に(2)は思いもよりませんでした。ちょっと驚いたので、知っている学校で初年度の「プログラミング入門」に使われているC言語の教科書を見てみたら、なんと、確かにほとんど触れられていませんでした。ポインタのインクリメントの項で申し訳程度に脚注で「char は1バイト、int は4バイト、double は8バイト」と書いてあるだけでした。そもそも2進数や2の補数表現などについても言及無し。これならわかるわけないですね。 引き続き回答をお待ちしています。

プログラミング | C言語関連426閲覧xmlns="http://www.w3.org/2000/svg">500

ベストアンサー

3

3人がナイス!しています

ID非公開

質問者

2021/2/28 19:06

> void print_matrix(int **mat); > これではうまく実行できない。なぜか? という感じです。 この期待を持ってしまうのが、私にはちょっとわかりませんでした。 int型の二次元配列は、特に細工をしなければ、すべてのint型データが一続きに並んだだけのものであって、「行ごとのint配列の先頭ポインタ」の配列になっているのではない、と考えるのが自然かと思いました。そうすると、二次元配列のポインタといえども、それをダブルポインタで表せるだろうという期待は出てこない気がします。うーん。どうでしょうか?

ThanksImg質問者からのお礼コメント

多くの人の事例を募った質問なので、回答をいただいたすべての方を「ベストアンサー」としたいところですが、システム上一つに絞れということなので、ご自身の入門時の事例を具体的に書いてくれた点からこの方をベストアンサーとさせていただきます。ここに回答いただいた皆さんにも入門者に教えるときなどに参考にしていただけるような、知恵を集める知恵袋にふさわしい質問と回答になったかと思います。ありがとうございました。

お礼日時:3/8 17:31

その他の回答(10件)

0

私もポインタ周りで躓いていたので。 ------------------------------- まず一つ目。 『変数』と『ポインタ』の使い分けがわからない。 二つ目。 サンプルが悪すぎる。 これにつきますね。 ある程度、理解した今でも、サンプルコードを見ると、逆にわからなくなります。 大抵の書籍やサイトでは、『int型変数とint型ポインタを比較している』ことが多いです。 でも逆に考えてみてください。 現実世界でいえば、『1~2kgの荷物を1~2kmの距離を運ぶために、ヘリを何百台もチャーターするようなもの』です。 変数と大差なく、簡単に使えるなら『こういう方法もあるよ』程度だとも取れますが、ポインタって、理解してないとバグのもとになりますよね。 だからJavaやC#とかそういう言語では『ポインタを意識させない作り』になっているのでは。 それなのに、int型変数と比較する意味が分かりません。 int型変数でも、処理系によりますが、大きくてもせいぜい 8バイト。 小さい場合はもしかしたら1バイトか? ( Windowsだと 4バイトだった気がしますが ) 対してポインタは? 大体 4バイト。 あれ? 差がほとんど無くない? あるいは、C#でいうプロパティのように、変数自体では、 a = 100; とかができないため、ポインタを介してアクセスする……みたいな役割なら理解できます。 でもポインタを学ぶ前に変数の項目ですでにアクセスしているやん。 だったら、なんなの? って感じでした。 で、いろいろ言語を扱ったり、コーディングしたり、いろいろ考えたりして、 データ構造とアルゴリズムの『リスト構造』をやったときに、 「あれ? (C言語での)リスト構造でのデータってどこにあるんだろ…?」と引っかかり、いろいろ調べて、『メモリ上にデータが配置されている』ことに気が付きました。 それでやっと理解できたのです。 どこにデータが入っているかがわからないから、使い分けが思いつかない。 『ポインタはアドレス』とか言われても『ポカーン("゚д゚)』だし。 アドレスだからなんなの? コンピュータ(あるいはコンパイラとか)が勝手に解釈しているだけじゃないの? って本当に困っていました。 今はある程度理解しているため、そんなに問題はないですが。

なんていうか、「米俵を分解すると、こうできますよ」みたいな意味不明な説明にしか感じないのです。 原理を説明せずに、『わかる俺すげー』感が半端ないです。 だから大抵の人が思考停止するのでは。

0

変数のメモリへの割り当てイメージが無いのでしょう。 C言語でいろいろ説明するより、アセンブラを読むのが手っ取り早い。

1

===== 例1. 実際の難しいプログラムを見て理解できない。 ↓ 理解できない箇所にポインタが使われている。 ↓ ポインタが難しいから理解でないと思う。 昔(20~30年位前)のC言語のプログラムはポインタをよく使う傾向にあった。難しいプログラムはポインタに関係なく難しいのだけど、その難しさにポインタの使用も少しは関係していた。その人は、「このプログラムが難しいのはポインタだ。ポインタは難しい。」と思う。 ===== 例2 「++」や「+=」を見てどういう意味かと聞く人がいる。明らかにC言語の文法(構文)を学習していない。そういう人にポインタの意味を聞かれて30秒ぐらいで説明したとする。その人は、理解出来ない、難しいと思う。

1人がナイス!しています

0

C言語における変数への代入が、即値でしか理解してないからポインターが分かりづらいのだと思います。 即値でも、変数はそのアドレスに格納されているデータを示していると理解出来る人なら、難しい事は無いと思います。 というか、ポインターという名前をやめて、アドレスにしてしまえば分かりやいのかも知れません。 結局、ポインターって呼んでるものは、(ulong)や(ulonglong)にキャストしたらアドレスが入ってる訳です。 ポインター変数にはこのアドレス値が即値で入ってて、その即値の示すアドレスにデータが入ってると分かれば、何も難しいことは無いと思います。 int a = 123; int *b = &a; この時 *b = aの値 b = aの値があるアドレス これだけ分かれば、2重ポインターとかも普通に理解出来るでしょうね。 逆にこれだけ学ばせれば、 int ****c; とかも理解出来るはず(さすがに4重ポインターなんて使わないとは思うけど)。 それと、宣言で初期値を代入する時に*がついている時と、再代入の時の*がない時が混乱するのかも? そろそろC++式の記述にしたら、少しは理解しやすくなるのかと知れません。 int *a ではなく、 int* a みたいに。

1

な~んて言う人の中にも実のところ基本的な使い方を暗記しているだけって人は多いんですよね。 本当に理解しているなら、他人が躓く理由も察することができるはずだしね。 さて。 ポインタがわからないって言う人は、根本的な話として「変数」というモノの実体が掴めてないとか、CPUがメモリに対してデータを読み書きする様がイメージできないとか、そういったコンピュータの基礎的な動作が理解できてないんですよ。 逆に言えば、そういうコンピュータの基礎を最初にキチンと身に付けることがC 言語を学ぶにあたって肝要になりますね。 なんせ機械語を習得してる人に対してはたった一言「要するにレジスタ間接アドレシングだよ」で説明できてしまう程度のことだしね。

1人がナイス!しています

ID非公開

質問者

2021/3/1 10:40

コンピュータがメモリ上に変数の値を記憶している様子を知っておくことはもちろん必要ですよね。あまりに基本的なことなので、ポインタを使おうという人なら誰でも知っていると思っていました。それこそ、電子レンジを使う人なら誰でも、極性分子である水分子に その固有振動数に合わせた電磁波を当てて揺さぶることで温度が上がるということを知っているくらいには。しかし実際には、意外にも、C言語の入門書ですら説明されていないということで、驚きました。いや、知ってて当然だと思うから執筆者も省いているのだったりして。そういえば、電子レンジの説明書にも上記のことは書かれていなかったかも。当たり前すぎるから?