ポインターの良い説明は何ですか?[閉まっている]


72

あなた自身の研究で(あなた自身で、またはクラスで)、最終的に、本当にポインターを理解した「あはは」の瞬間がありましたか?特に効果的と思われる初心者プログラマ向けの説明はありますか?

たとえば、初心者がCで最初にポインターに出会ったとき、コンパイルされるまで&sと*sを追加するだけです(私自身もそうでした)。おそらく、あなたやあなたの学生のためにポインタを「クリック」させたのは、写真、または非常にやる気のある例でした。それは何でしたか、それがうまくいかない前に何を試しましたか?トピックの前提条件(構造体、配列など)はありましたか?

つまり、&sおよびの意味を理解するために必要なのは*、自信を持ってそれらを使用できる場合ですか?構文と用語やユースケースを学ぶだけでは十分ではなく、ある時点でアイデアを内部化する必要があります。


更新:私はこれまでのところ答えが本当に好きです。どうぞ来てください。ここには多くの素晴らしい視点がありますが、概念を内面化した、私たち自身にとって多くは良い説明/スローガンだと思います。私はそれがあなたに夜明けになったときの詳細なコンテキストと状況を探しています。

例えば:

Cでは、ポインターを構文的に少ししか理解していませんでした。2人の友人がポインターを別の友人に説明しているのを聞きstructました。最初の友人は、それをどのように参照および変更する必要があるかについて話しましたが、それは私にぶつかった他の友人からの短いコメントでした:「より効率的です」。16バイトではなく4バイトを渡すことが、私が必要とする最後の概念的なシフトでした。


16
「ショットガン」メソッド:動作するまで* sをスローします。
マイケルK

15
@マイケル:うん、それで幸運。
ロバートハーベイ

8
この質問は、SOの各学期の開始直後に発生します。最新版はこちら:stackoverflow.com/questions/4118647/...
ティム・ポスト

10
ポインターの良い説明は何ですか?ブライアンカーンヒガンとデニスリッチーは、ソフトウェアエンジニアが嫌いです。
アダムクロスランド

3
デバッガーでマシンコードをシングルステップ実行した後、「クリック」されました。はい、コンピューターアーキテクチャの基本に精通していました-Commodore 64でアセンブリを学び、その後x86 ASMは非常に簡単でした。だから私はすでに「アドレス」の概念を知っていたが、それがCの構文構造にどのようにマッピングされるか理解できなかった。
zvrba

回答:


25

グリッドとしてのメモリ図

通常、私が行うことは、メモリを「グリッド」として表現することです。そのため、アドレスを作成し、異なるメモリ空間を強調表示し、セルの値(またはさらにバイナリ表現)を書き込み、メモリ内のポインタをそれらの値にリンクできますを指す。(それから、それが単純化であることに言及してください)。

通常、ほとんどの生徒にとっては「ああ」の瞬間です。

シンボルジャグリング

その後、&と*の使用方法を忘れないようにすることは非常に簡単です。数学や物理学の計算と同じように提示します。km単位の距離を時間単位の時間で除算すると、km / h単位の速度が得られます。何が出ている必要があります。シンプル。

救助へのprintf

あなたがこれらで説明したことを視覚的に表すいくつかの基本的な例を行うことは、彼らが彼らが理解したと思うことで彼らを慰めるか、「ああ、私はこれを取得しません」と言う機会を与えます。

広範囲に

単純型のポインターをカバーし、アドレス指定とデータ型のサイズの違いを理解していることを確認してから、構造体、配列、および複数のレベルを確認します。

次に、ポインター演算を開始します。


補遺:再帰

通常、視覚的な表現を使用して、再帰を同様に説明します。単一の文字を書き込む事前に作成された関数を使用してアルファベットを印刷し、2行変更するだけで逆の順序で印刷するように依頼します。

通常、「何が...?」そして、数値を印刷してステップをインデントするためにprintfに別のパラメーターを追加すると、安reliefの溜息になります。


代替案:Play-Dohモデルとウォーターカップ

私は実際に大学に同僚を何人もいましたが、学生たちに遊び道のりを使ってポインターと記憶へのアクセスを説明するビデオを見せました。それは信じられないほど巧妙でよくできていましたが、プログラミングを把握することに興味のある非常に若い学習者を除いて、私は自分でそのテクニックを実際に使用したことはありませんでした 基本的には、プレイスペースの小さなボールを使用します。これは、メモリ空間を表す他のプレイボールのより大きなボールにアタッチでき、それらをリンクして(リンクされたデータ構造のように)、またはマージして(連続したように)メモリ空間)。指し示されているメモリ空間に異なる色を使用すると、ポインタも役立ちます。しかし、まだグリッドとしてのメモリの方がうまくいくと思います。ポインティングは、実際には「マップ/グリッド」のように、「アドレス指定」の問題であることを明確に示すことができます。一方、Play-dohモードでは、メモリ内で物事が互いに「触れ合う」と考えるように混乱させます。

ウォーターカップは同僚によっても直接使用されましたが、彼女がそれを思いついたかどうかはわかりません。興味深いアプローチでしたが、多くの学生が説明に戸惑っていることに気付きました。DevSoloのコーヒーカップテクニックに似たもの。しかし、学生にコンテナ、データ構造、ポインタ、配列を混同させるのは、実際には誤解を招くものだと思います。最初に配列を説明するのは興味深いアプローチかもしれませんが、あまり長くは使いません。


うわー、賞金に感謝します。答えがありがたかったです。
ヘイレム

それを引き出します:| 良い教えのようですね。
スパイ

80

私がかつて言ったよりも賢い人:

修道女のウー・ジンチャンは、第六パトリック・フイネンに「私は長年マハパリニルヴァーナ経典を研究してきましたが、まだよくわからない分野がたくさんあります。教えてください。」

「私は文盲です。キャラクターを読み上げてください。おそらく意味を説明できるでしょう。」

修道女は言った、「あなたは登場人物を認識することすらできない。それではどうやって意味を理解できるのか?」

「真実は言葉とは何の関係もない。真実は空の明るい月に例えることができる。この場合、言葉は指に例えることができる。指は月の位置を指すことができる。しかし、指はそうではない。月。月を見るためには、指を越えて注視する必要がありますよね?」


13
月を間接参照するための+1。可能であれば、koの+1。
ティムポスト

14
1本の指で投票する音は何ですか?
アダムクロスランド

3
@Adamは、マウスを使用しているかトラックパッドを使用しているかによって異なります。
ダニエルジョセフ

7
@フランクそれは素晴らしい引用でした。それでも私はそれがアイデアを把握するのに役立つとは思わない。特に、ポインターが初めての人に。
グルシャン

11
これは美しい物語です...しかし、私は人々がそれがポインタをうまく説明しているというよりも、そのために賛成しているのではないかと疑っています。
キラレッサ

46

図が非常に役立つことがわかりました。例:

ポインター図


この種の図は、ポインターがそれ自体の変数であるが、別のオブジェクト、つまり配列または文字列の場所である値が含まれていることを確認するのに役立ちました。また、鉛筆で行うと、紙や黒板/ホワイトボードでプログラムをトレースできます。


4
「ポインタ」内の値は4であるか、配列インデックス(またはメモリアドレス)は0から開始する必要があります。
MAK

++これはまさに私がそれを説明しようとしていた方法です。私はFortranで始めました(良くも悪くも!)。Fortranでは、当時、構造体の配列の代わりに並列配列を使用していました(newなどはありません)。1つの配列に配列内の「別の行」のインデックスが含まれている場合、それを「ポインター」と呼び、これは刺激的でした。リンクリスト、ツリーを作成しました。
マイクダンラベイ

2
ポインターは、何がどこに保存されているかを示す画像と、ポインターが指す場所を示す矢印を使用して最もよく説明されています。
ギャブリン

32

ポインターについて最初に「学習」したとき、私はある種のポインターに夢中になりました。私の大学は、私がJavaを中心としたカリキュラムの中心に登録する前に決定を下していました。そのため、データ構造教授がCについて1つの講義を行い、方法私の頭の上に。

定義を理解しました:

ポインターは、変数のアドレスを含む変数です

しかし、私はまだ概念の大部分を理解していませんでした。振り返ってみると、それは3つのことを中心にしたと思います:

  1. メモリロケーションとは正確に何ですか?(当時、私はコンピューター組織の授業を受けていませんでした)

  2. 厄介な構文(だから...なぜ「int * ip」のように正確に定義されていますが、その後変数を「ip」と呼ぶのですか?)

  3. 変数を使用するだけでなく、変数のアドレスを保存することはどのくらい正確に有益ですか?

K&Rの本を購入してすべての問題を解決するまで、ポインターを把握することはできませんでした。私が長い間Co​​mputer Organizationクラスを完了したという事実(Cを学ぶ前に必要だと思う)に加えて、その一部は、関数、配列、構造体にポインターを使用できることに気づいたという事実に関係していました...通常の変数のアドレスのストレージとしてだけでなく、有用なことを行うため。

しかし、私の "aha"の瞬間は、K&Rが単純なポインターを定義する厄介な構文を説明する方法でした。私は本全体でメモを取りました(本の理解を深めるために、本のポイントを自分の言葉に言い換えます)。これはそれに関連するものです。

ポインターは、変数へのアドレスを含む変数です。ポインターは、「*」演算子を使用して定義および間接参照されます(ポインターが指すメモリー位置に格納されている値を取得します)。式はニーモニックです。

Ex.: 
   int a;      /* Variable 'a' is an integer */

   int *ip;   /* Variable ip is a pointer and dereferencing it gives an integer.
                 In other words, the expression *ip is an int, so ip is a pointer
                 to an int */

私は頭の中にこんなに基本的なものが染み込むまで、ポインターのより高度な概念を完全に把握できないといつも感じていました。その割り当ての後、私は何度も悩まされていました(ちなみに、あまりうまくいきませんでした;))。これをマスターすることは、関数ポインターなどのポインターや、次のようなより複雑な定義を含む、より高度な概念にとって不可欠です。

char (*(x())[])()

全体として、ポインターの概念には次が必要だと思います。

  1. コンピュータでメモリがどのようにレイアウトされるか(およびメモリとは何か)の基本的な理解。

  2. 強力なポインターがどれだけ強力であるかの知識(学習のために学習する単なる別の抽象的な概念ではなく、実際の使用法)。

  3. 「ポインターの定義」として口語的に知られている象形文字を解読する

全体として、ポインターについて学習するとき、少なくとも3つの「あは」の瞬間があるはずだと思います。私はまだ学生ですので、コンセプトを学ぶのがまだ(比較的)新鮮な人の視点に感謝すると思います。


3「Ah ha!」の+1 モネンツ。Grokingポインターはレイヤーで提供されます。ポインターへのポインターが半分しか理解されていないことに気付く前に、私は長い間ポイントを「理解していました」:
バイナリウォリアー

「ポインタを理解しない」ことの非常に大きな部分が、実際には奇妙なC構文につまずいているという点で、あなたは完全に正しいと思います。[考えます:この種の構文を理解するのはどれほど難しいでしょうか。PointerTo<int> a]
Benjol

合意、@ベンジョル。構文int* ipが一般的でないことに驚いています。このようにフォーマットされたコードを見て、ようやくポインターの理解を始めました。次に、「ipはint型のポインターです」と読みます。
ジェイコブ

19

ポインターは、デスクトップ上のアプリケーションのショートカットに少し似ています。ショートカットを削除しても、ターゲットはまだ存在しています。ショートカットを起動すると、ターゲットが開始されます。

私はいつも、デスクトップにtxtファイルを作成し、そのファイルへの2つのショートカットを作成することで、この仕組みを説明しています。ショートカットをコピーして削除すると、「参照」の背後にある考え方を人々が理解していることがわかります。

グループがショートカットの背後にある基本を理解したら、必要に応じてポインターの説明を開始できます。彼らはおそらくそれをかなり簡単に理解するでしょう。


それは悪い例えではありません。これを文字通り「ハードリンク」とする人のために追加するほんの数ポイントは、ディレクトリを変更しても常にターゲットを指し、オブジェクトが再配置されてもポインタは元のメモリを指します。「ハードリンク」は、ターゲットが存在しなくなったときに、ダングリングポインターポインターをNULLに設定する必要があることを示します。
snmcdonald

ハードリンクは、参照カウントスマートポインタのようなものです
JK。

1
+1。ポインターを説明するための最も実用的なアナロジーの1つ。この機能は誰もが最もよく使用するものであるため、学生はすぐにアイデアを得るでしょう。
カルティクスリーニバサン

13

8〜10年前、私はコミュニティカレッジでイントロ「C」コースを教えました。これは常に探検する楽しいトピックでした。うまくいくように思われたのは、同僚と数回話し合った後、コーヒーカップと手を使うことでした。

コーヒーカップ(または配列の場合はそれらの行)の類似性を変数(何かを保持できる)として使用しました。それから手も使った。それは何かを握ることもできるし、人差し指をコーヒーカップを「指す」ように伸ばすこともできる。

近い手はヌルで、私の頭を指している指(モックガンのような)はぶら下がりポインターでした。

その後、いくつかのデモンストレーションとデバッガーのトリップで、ほとんどの場合クリックしました。


3
あなたはすでに私を混乱させました。
kirk.burleson

1
@カーク、どうやって?解決できるかどうか見てみましょう。
-DevSolo

4
++これらのことについて考えさせるために教えることほど良いものはありません。
マイクダンラベイ

私の大学の講師の一人は、コーヒーカップの代わりに、学生(追加の笑い方は「ニール」)を使って、同様のことをしました。聴衆に手を振るのは、何かを指している可能性があるため、ぶら下がりのポインタでした。
カズドラゴン

2
宙ぶらりんのポインターは、ニールを指してから、あなたが指している場所を変えずに椅子から離れるようなものです...その後、そのポインターを追跡し、誰がそこにいるかに関係なく、ニールとしてそこにあるものを解釈しようとします。
ジョンパーディ

10

「どのようにしてポインタを把握したのか」という質問を聞いたとき、私は本当に非常に心配しています。私はいつもコンセプトが信じられないほどシンプルであり、言語の論理的な進化がプログラマに大きな力を提供すると考えていました。

私が心配しているのは、ポインターの概念を理解するのが難しいことは一度もなかったことです。したがって、ここで「最終的にはいつそれを手に入れたのか」と何度も何度も考え始めます。

実際に入手できますか?たぶん私はしなかった?

コンセプトがトリッキーなように見えるのは、まだ遭遇していないすべての人にポインターが非常に難しいことを伝え続けているからかもしれません。

もちろん、そのアイデアをそこに放り出して、もちろん個人的には良い図が大好きで、スティーブギブソンは常に何かを説明する素晴らしい仕事をしています!


おもしろい...当時どの言語を使っていましたか?C構文は多くの人をつまずかせると思います。最初にアセンブリを知っていれば、それが理由の1つであることがわかりました。[ところで、これに投票したいのですが、今日は上限に達しました。]
マクニール

興味深いことに、私は長い間「危険な」ポインターの知識がなく、Python(および大学のJava)で働いていました。それから、C ++を選択言語として使用する「オブジェクト指向メソッド」モジュールを取り上げ、そこに直接入り込みました。
マーカスワイブロウ

また、プログラムがメモリでどのように表現されるかを理解することは間違いなく助けになると思いますが、ポインタが言語に役立つ追加である理由を理解することは、最も効果的な角度であると思います。元のデザイナーとして処理します。
マーカスワイブロウ

+1ポインタが難しいとか神秘的だと人々が考える理由がわかりません。
-ggambett

ええ、ポインターは常に非常にシンプルで便利なため、「難しい」と思うことは想像できません。コースの教師が「今、これは少しトリッキーです」と言ったとき、私はそれが嫌いです。なぜならそれはまさに破壊的だからです。いまいましいものを教えて、生徒たちにそれがトリッキーだと思うかどうかを自分で決めさせてください。
ジョンパーディ

7

私はCのポインターに大きな問題は一度もありませんでしたが、それは最初にアセンブラーを学ばなければならなかったためかもしれません。実際、自分でアドレスを管理する必要がなくなったことは、実際に安心でした。そのため、おそらく答えは(これがあなたが教えていることだと仮定して)、生徒にエミュレートされたアセンブリ言語を提供することです。彼ら、「Hello、world」よりも洗練されたものを書くプロセスでそれ理解します。


アナロジーを使用しようとするのではなく、より原始的な抽象化を適応させるために+1。
匿名タイプ

私の高校では、コンピューター研究の1つのユニットが、実際のコンピューターに触れたり関与したりすることなく黒板から教えることができるマッチ箱コンピューターの研究に専念していました。
rwong

@ラリー・コールマン、アセンブリ!!!!!!!!!!! Cの前に最初に試してみたい。どこで学習を始めるか教えてください。無料の電子ブック、無料のPDF?IDE?お願いします!!!!!!!!!!!!!!!!!!!
スペースズライ王


6

ポインターについてどうやって学んだのですか?大学の新入生の年に簡単なコンパイラを書くことによって。

素人の言葉でポインタを説明するには?私は、インデックスカードに保存されているライブラリカタログの(日付は?)類推が好きです。各カード(「ポインター」)には、一部の本(「データ」)の場所に関する情報が含まれていますが、実際には本自体は含まれていません。カードを変更する場合(「ポインター演算」)、それが指すのは本が指す本を変更するだけで、本自体には影響を与えません-アドレスを台無しにしないように注意してください。または間違ったライブラリですらあります。ただし、カードの「アドレス」に従ってライブラリの適切な部分に移動すると(「ポインターの逆参照」)、本自体を表示/変更できます。


正確にその説明があったCSコースの記憶のために+1
ゲイリーロウ

カードは実際は本がどこにあるかを言っていないので、それはある意味では良いが、やや誤解を招く。それでもスニーカー指向の検索アルゴリズムを実行する必要があります。たぶん、これはデータベースをより良くモデル化します-キー(呼び出し番号)によって保存されたオブジェクトを参照します。
DarenW

+1 Barfieldmvによって説明された概念と同じ概念を保持していますが、より現実的なアプローチをしています。
カルティクスリーニバサン

5

ポインターを学習しようとしている人は、通常の変数が何であり、Cでどのように機能するかを知っていると仮定します。

  • これらも変数ですが、性質は異なります。可変空間に2つのレイヤーがあると仮定します。さまざまなタイプの通常の変数は、上位層にあり、ポインターは下位層にあります。この図のように

    代替テキスト

  • 「ポインター」という名前が示すように、ポインターは何かを指すことができます。指が何かのオブジェクトを指すことができるように。彼らが指し示すものは何ですか?これらは通常の変数です。要するに、「ポインターは通常の変数を指します」。

  • 通常の変数と同様に、ポインターもint、char、floatなどの同じ数の型です。また、特定のタイプのポインターは、同じタイプの変数のみを指すことができます。
  • ポインターは1つの変数を指すことができ、後で同じポインターが別の変数を指すことができます。タイプだけが同じでなければなりません。したがって、ポインタと変数の関連付けは永続的ではなく、変更できます。
  • それでは、ポインターはどのように宣言されますか?通常の変数とほとんど同じです。名前の前にアスタリスク(*)を付ける必要があります。好む-

    int *pointer;
    
  • 次に、ポインターが変数にどのように関連付けられていますか?&このステートメントのように変数の前に演算子 を使用する-

    pointer = &variable;
    
  • 変数を指すことにより、ポインターはどのように使用されますか?これは、名前の前にアスタリスク(*)を付けることによっても行われます。次に、現在指している変数の場所で使用できます。

    *pointer = var1 + var2;
    

    の代わりに

    variable = var1 + var2;
    
  • 次に、いくつかのコードを使用してポインターを操作します。ポインタのこの特性に今すぐ慣れてください。ここまでは、ポインターが何をするかについて話していました。いったん問題がなければ、ポインターが変数を指し示し、通常の算術演算が変数に適用された場合にどのように反応するかを調べ始めます。次に、ポインターと配列の間の関係、およびポインターへのポインターを探します。

これが、ポインターの学習について提案するすべてです。


私は「最初にそれから何をするのか」というプロセスに従うことを望みました。抽象化!
グルシャン

5

質問の改訂された要件をサポートするために編集

「ポストポインター」の理解への私の道(正しく思い出せば)はこのようになりました。私はまだBBC Microをいじっていた頃からアセンブリプログラミングの簡単な経験があったので、一連のボックスとしてメモリの概念がありました(これについては以下を参照)。これは、アレイの使用によって強化されました。しかし、私はCの世界に入り、文字列を扱う必要があり、それはポインターを意味していました。BASICではこれは些細なことでしたが、アセンブラではそれらを操作する必要はありませんでした。今では古典的なCではすべてのポインタとものがあります。ああ、しかし、次のような(nullで終了する)文字列を持つ配列に戻ることができます:

char s[] = "Hello, world!";
printf("%s",s);

それは、文字の配列(私の小さな世界では1文字あたり8ビット)であり、末尾にゼロ文字があり、どこで終わるかを示しています。printfはその配列を取得し、それを実行して印刷します。しかし、この文字列を関数に渡したい場合はどうなりますか?

void print_str(char* p) {
  printf("%s",p);
}

マニュアルに書かれていることですが、それは何ですか?うーん、char *は「charへのポインター」を意味します。OK ...私を失いました。それから、char *がpをs [0]と等価にすることがわかりました。OK、私はそれを使用することができますが、私はまだポインターが何であるかをいじっていません。つまり、これらのいずれかのデータを設定するにはどうすればよいのでしょうか?マニュアルに戻りましょう...

char* p = "Hello World!";

上記を書いているときに、「charへのポインタを宣言し、この文字の配列に等しく設定する」と言っています。どういうわけか、そのポインターは配列の必要性を排除します。変更のためにコンパイラが何らかの処理を行っていると思います。それでは、このポインターで配列を変更するにはどうすればよいですか?配列バージョンを使用できることを知っています

 s[2] = 'L'; 

しかし、「ポインタが話す」に相当するものは何ですか?もう一度そのマニュアルに...

*(p+2) = 'L';

私は、*は、単に「メモリアドレスの内容」を意味しているとし(p+2)ていますs[2]。これは、ポインタpが...ただ...アドレス... bongであることを意味しました!

悟りの音があること。私は突然ポインターを細かくしました(それはかなり前のことで、私たちの古いタイマーは後まで「グロッキング」しませんでした)。それは単なる間接的なものでした。


元の:

OK、私の2cの価値:

記憶が箱の束であると想像してください。各ボックスには、側面(アドレス)に番号があります。各ボックスには番号(内容)が含まれています。これらのボックスは、変数(ボックスNのコンテンツが必要です)、ポインター(ボックスNにあるボックスのコンテンツが必要です)の2つの方法で操作できます。ポインターは単なる間接です。

そして、あなたが知る必要があるすべてをカバーする大きな答えのために- これを読んでください


++それは多かれ少なかれ私が主題を教えた方法です。
マイクダンラベイ

OP要件をサポートするために記事を編集しました。
ゲイリーロウ

文字列の最後に余分なNUL文字を追加したマニュアルを使用しましたか?
ロブ・ギリアム

@raimesh非常に古いもの(1991年頃)。どっちが思い出せない。
ゲイリーロウ

1991?これはC言語のマニュアルとしては古くはありません。K&Rの第1版は1978年に公開されました。文字列定数の最後に\ 0を付ける必要があることを示唆するマニュアルが出回っていることに興味をそそられました。(実際には、再びそれを見て、あなたは\ nを置くことを意味したのか?)
ロブ・ギリアム

4

木材のいくつかの小さなブロックを取得します。

金属フックを一方の端に追加し、金属の目をもう一方の端に追加します。

プレイできるものでリンクリストを作成できるようになりました。

この物理的な小道具で説明してみてください。私は、1年生(新入生)の生徒にポインターを教えるときにこれがあればいいのにと思っていました。

小さな金属製のフックはポインターであり、物が指し示す木の塊です。

私はブロックで遊んだ後にそれを取得しないように誰も定義します。


4

すべての綿毛を取り除き、ポインターを魔法の実体ではなく他の変数として扱い始めたときに人生が楽になりました(11年前の昔)。

  1. ポインターは、別の変数のアドレス(または任意のアドレス)を格納する変数です。
  2. *は、ポインタ変数に格納されているメモリ位置の値を取得するために使用されます。
  3. &演算子は、メモリ位置のアドレスを提供します。

残りは構文糖衣と常識です。.いくつかの単純なCプログラム(リンクリストライブラリの実装など)を作成して、ポインタを使用してハングアップさせます。


2
  1. ポインターは、配列へのインデックスの一般化と考えることができます。
    • 大きな配列は、小さくて、重なり合わない、可変サイズの配列に分割できることを考慮してください。現在、これらの小さな配列は、通常配列と考えられています。大きなものは、コンピューターのメモリスペース全体です。より小さな配列を切り刻むプロセスは、メモリ割り当てと呼ばれます。
  2. いくつかのポインタによって互いにリンクされている構造のセットは、有向グラフと考えることができます
    • 各頂点は、何らかの値を保持できる変数です。
    • 一部の変数はポインターであり、各ポインターは他の何かへの発信エッジを1つだけ持つことができます。
    • ポインターではない変数には、出力エッジがありません。それらは、任意の数の着信エッジを持つことができます。

2

私はポインターの周りの状況をまったく覚えていませんが、その瞬間、cスタイルの配列の理解に関する記憶を遡及的に再構成しました。(つまりarr[3]、と同じです*(arr+3)

何らかの理由で、ポインターの状況が発生するたびにポインターを配列として表示すると非常に役立ちます。


2

基本的に、@ Gary Roweは適切なモデルを導入しました。アドレス(数字)が付いた一連のボックスとしてのメモリ。各ボックスには値(数値)が格納されます。

ポインターの概念は、あるボックスの値を別のボックスのアドレスとして解釈することです。この値は特定のボックスを参照するために使用されるため、referenceと呼ばれます。したがって、参照解除とは、参照されているボックスを開くプロセスです。

if vが変数(ボックス)の場合、ステートメント

  • vの値を意味しますv。つまり、箱の中にあるものを教えてください
  • *vは、の値を逆参照することを意味しますv。つまり、値が参照するボックスの内容を教えてくださいv
  • &v参照を意味しますv。つまり、ボックスに住所を教えてください

ポインタをまったく異なるものとして導入するという目的を果たすものではないと思います。私が子供の頃、それは私にとって理解しにくい概念でした。それは常に、私が本当に理解したことのない暗黒の魔法のように見えました。初めて理解したのは、ポインター演算を持たない言語で二重間接を使用する小さなゲームを書いたときです。それは私を啓発しました。

ポインタは解釈の問題です。それを説明すると、物事がずっと簡単になると思います。また、10個の変数のメモリを使用した簡単な例を示した場合、ポインター演算は非常にシンプルで直感的な操作です。


2

私が本当にびっくりした説明は:

土地の上にさまざまな家が建てられた都市グリッドを考えてみましょう。あなたの手には一枚の紙があります。あなたが書いた論文に:


デビッドの家、

112まあまあの通り。


紙(ポインター変数)には、Davidの家を指す住所が含まれています。友人にデビッドのクールな家を見てもらいたいときは、実際の2階建ての建物を郵送するよりも、家の参照として紙を使用する方がはるかに簡単です。

本物のポインタと同様に、紙のアドレスをたどるといくつかの問題が発生する可能性があります。デビッドは動いたかもしれませんが、そこに着くと、地面に大きな穴があります。この場合、Davidが移動したときに紙のアドレスを消去するか、少なくとも新しいアドレスに変更する方が良いでしょう。また、住所に行って、友人のデビッドのリビングルームと思うものを入力することもできますが、今回は完全に見知らぬ人のプールに行き着きます。他の誰かが、あなたが持っていたアドレスのスペースを、まったく異なるものに使用しました。


2

ポインタを説明する場合は、最初にメモリを説明する必要があります。私は通常、行と列を持つグラフ用紙/正方形の用紙を使用してそれを行います。「学生」が記憶を理解していれば、彼女は住所とは何かを理解できます。アドレスを取得すると、ポインタを取得します。

この抽象化で遊ぶことができます。たとえば、ある正方形のアドレス(番号)を別の正方形に書き込みます。次に、ポインターの四角形から目的の四角形に矢印を描画します。次に、ポインターを上書き(増分など)し、矢印を調整します。別の広場に住所を書き、生徒に矢印を描かせます...

次のステップ:特定の四角形(ポインターなど)に名前を付けます。これで、逆参照を説明できます。それでおしまい。


2
実際に電子を使ったものに手が届く前に使っていた「コンピューター」を思い出します-段ボール「CARDIAC」と呼ばれると思います。文字通り、番号付きボックスに数字を書いて、他の番号付きボックスから番号を取得します。それ教育的なものであり、実際のマイクロプロセッサー上のポインターを理解するのに問題はありませんでした。
DarenW

2

おそらくそれは私だけかもしれませんが、私はアナロジーでうまく動作します。だから、他の誰か(異なる機能/クラス)、 "Bar"を持ちたいと思っている友人(関数/クラス) "Foo"があるとしましょう。何らかの理由であなたに連絡します。「フー」は「バー」を見に行くことができますが、それは便利ではなく、それらすべての存在(インスタンス)を移動させます。ただし、「Foo」は「Bar」に電話番号(ポインター)を送信できます。そうすれば、あなたがどこにいても、「Foo」はあなたを見つけることなくあなたに連絡する方法を知っています。

また、「Bar」には知り合いの「Baz」がいて、彼もあなたと連絡を取りたいとします。しかし、あなたはあなたの電話番号を守っており、誰も持ってほしくありません。「Baz」は「Bar」(ポインターとしての電話)を呼び出すことができます。そして、「Baz」の友達や友達の友達のチェーンをたどっていきます。


2

アセンブリ言語やコンピュータアーキテクチャを学習している場合、ポインタのが理にかなっています。Cクラスを教える場合は、数週間のアーキテクチャから始めて、メモリモデルとプロセッサが実際に実行する命令の種類を説明すると思います。


絶対に。レジスタを処理し、即時値や間接アドレス指定などを理解すると、ポインターの概念全体が直感的に理解できます。Cの最初の行を書く前に6502アセンブリ、次に68Kアセンブリを習得したので、ポインターを紹介するまでに、コンパイラー(中間)アセンブリーを調べたところ、予想どおりでした。
ラジアン

2

私の「あは!」このチュートリアルでは、

Cのポインターと配列に関するチュートリアル

正確には、この章で説明しました:第3章:ポインターとストリング

さらに正確に言うと、次の文が付属しています。

puts()に渡されるパラメーターはポインターです。これはポインターの値です(Cのすべてのパラメーターは値で渡されるため)。ポインターの値はポインターが指すアドレス、または単にアドレスです。 。

私がそれを読んだとき、雲は別れ、天使たちはトランペットのファンファーレを吹きました。

あなたが見るように、私がそれ以前に読んでいたすべてのCチュートリアルまたは本は、Cが値または参照によって渡される可能性があると断言しました。真実は、Cは常に値で渡されるということですが、渡される値はたまたまアドレスであることがあります。メソッド内では、渡されたintでコピーが作成されるように、コピーはそのアドレスで作成されます。コピーは、ポインターが指す値で作成されません。したがって、メソッド内でポインターを使用すると、元の値にアクセスして変更できます。

私はCプログラマーになることはありませんでしたが、.NETプログラマーになりました。オブジェクトとオブジェクト参照は同じように機能します。オブジェクトへの参照は値によって渡されます(したがってコピーされます)が、オブジェクト自体はコピーされません。私は、ポインターを学んだことがないため、これを理解していない多くのプログラマーを回避してきました。


1

トリックは、パイプの写真がパイプではないように、モノの場所とモノ自体が同じではないことを説明することです。モノを移動すると、その場所が変わります。場所は残り、そこに何か他のものを置くことができます。


1

ポインターは、何かが役に立つ場所を示す付箋です。モノの場所を含み、モノの大きさを示します(とにかくCで)。したがって、ダブルポインターは、「冷蔵庫に6個のパックがあります」という付箋のようなものです。あなたは実際にそれがコーラであるかバドワイザーであるかを理解するために6パックを手に入れなければなりません。


1

コードを考えると:

int v=42; //単純な変数の宣言と初期化

int *p = &v; //変数vにポイントpを作成します

上記のコードについて次のことが言えます。

int * p // "int pointer p" ...これは、int型の変数へのポインターを宣言する方法です

*p //「pが指す」...これは、pが指すデータであり、vと同じです。

&v // "変数vのアドレス" ...これはpのリテラル値を表します


1

http://cslibrary.stanford.edu/

このサイトには、ポインタとメモリ管理を学ぶための素晴らしいチュートリアルがあります。

このサイトで提供されているポインターの基本、ポインター、およびメモリを確認することをお勧めします。また、リンク上のリンクリストの問題を確認して、ポインターの概念をさらに強化することもできます。


1

ポインタを説明するための鍵は、あなたが説明している人々がすでに記憶の概念を理解していることを確認することです。メモリが大規模な配列として存在することを信じて、彼らが本当に低レベルを理解していればいいのですが、インデックスの場所によって配列内の任意の位置にアクセスできることを理解すれば十分です。

メモリ全体をコピーするのではなく、インデックスの場所を渡すというコンセプトを持つ次のステップは、ほとんどの人にとって理にかなっています。そして、それはほとんどの人がポインタが有用である理由を理解するのに十分です。

ポインタを理解するための最後のステップは、すべてのデータが保存されているインデックス位置を保存するメソッドのメモリインデックス位置をパラメータとして渡す方法を説明することです。これは、一部の人々が対処するにはあまりにも大きな一歩になる可能性があることがわかりました。

これらの基本的な手順を誰かが把握したら、実際のデータオブジェクトを見つけるためにアドレスを確認する必要がある回数を追跡する限り、ポインターを無期限にチェーンできることを把握するのは簡単です。

誰かがポインターを把握したら、次にすぐに把握しなければならないのは、ヒープメモリとスタックメモリの違いであり、スタックメモリへのポインタがメソッド外に渡されると危険な理由です。


0

「Cパズル」などの本を覚えていますが、これは純粋に図書館で入手できる数少ないプログラミング/コンピューター関連の本の1つであったため、Cの理解は初歩的なものでした。それはあなたにC表現を投げ、それを表現するように頼み、ますます複雑になった。


0

私が大学にいたとき、私の教授はポイントをそれ自体の独立した変数として、メモリの場所への矢印(配列のように表されます)を描いた本当にすてきなパワーポイントのスライドを持っていました。矢印が変化したとき、ポインターが逆参照されたときなどを段階的に表示しますが、数分以内にそれを理解できない方法はありませんでした。コンセプト自体は本当に簡単ですが、それを正しく行うか、実用的なプログラムに適用するには、さらに練習が必要です。


0

その前に、プログラミングでは「すべてがメモリを使用する」こと、およびメモリ内の(静的な)変数割り当てについて説明します。また、メモリアドレスとは何か、メモリ空間、メモリアドレス、変数の関係についても説明します。

最後に、整数データ型と変数、文字列データ型と変数などがあることを説明します。メモリアドレスを格納する特別なデータ型があり、0 o ""のような空の値があることを説明するまで、nullと呼ばれます

そして、最後に、ポインターの使用を通じて動的に割り当てられた変数。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.