1 00:00:00,000 --> 00:00:02,520 [Powered by Google Translate] [セクション4 - より快適] 2 00:00:02,520 --> 00:00:04,850 [ロブボーデン - ハーバード大学] 3 00:00:04,850 --> 00:00:07,370 [これはCS50です。 - CS50.TV] 4 00:00:08,920 --> 00:00:13,350 私たちは、あなたたちがいることを知らなかった場合には、明日クイズを持っています。 5 00:00:14,810 --> 00:00:20,970 それはあなたのクラスで見てきたか、クラスで見てきたことがすべてでは基本的にです。 6 00:00:20,970 --> 00:00:26,360 つまり、彼らは非常に最近のトピックいるにもかかわらず、ポインタが含まれます。 7 00:00:26,360 --> 00:00:29,860 少なくとも、それらの高レベルを理解しておく必要があります。 8 00:00:29,860 --> 00:00:34,760 あなたはクイズのために理解しておく必要がありますクラスでオーバー消えていた何か。 9 00:00:34,760 --> 00:00:37,320 あなたがそれらの質問を持っているなら、あなたは今、それらを求めることができます。 10 00:00:37,320 --> 00:00:43,280 しかし、これはあなたたちが質問をして、非常に学生主導のセッションであることを行っている、 11 00:00:43,280 --> 00:00:45,060 ので、できれば人々は質問があります。 12 00:00:45,060 --> 00:00:48,020 誰もが疑問を持っていますか? 13 00:00:49,770 --> 00:00:52,090 はい。 >> [学生]は、ポインタを介して再度行くことはできますか? 14 00:00:52,090 --> 00:00:54,350 私はポインタを介して行くつもりです。 15 00:00:54,350 --> 00:00:59,180 あなたのすべての変数は、必ずしもメモリに住んでいる 16 00:00:59,180 --> 00:01:04,450 が、通常はそんな心配はありませんし、あなただけのX + 2とy + 3言う 17 00:01:04,450 --> 00:01:07,080 とコンパイラ、物事はあなたのための生活を送っている場所を理解します。 18 00:01:07,080 --> 00:01:12,990 一度ポインタを扱っている、今、あなたは明示的にそれらのメモリアドレスを使用しています。 19 00:01:12,990 --> 00:01:19,800 だから、単一の変数はこれまで、任意の時点で単一のアドレスに住むことになります。 20 00:01:19,800 --> 00:01:24,040 我々はポインタを宣言する場合は、どのような種類は次のようにするつもりですか? 21 00:01:24,040 --> 00:01:26,210 >> 私はポインタpを宣言したいと思います。タイプがどのように見えますか? 22 00:01:26,210 --> 00:01:33,530 【学生】int * pを。 >>うん。だからint型の* pを。 23 00:01:33,530 --> 00:01:38,030 そして、どのように私はそれをxにポイント作るのですか? >> [生徒]アンパサンド。 24 00:01:40,540 --> 00:01:45,300 [ボーデン]だからアンパサンドは文字通りアドレス演算子と呼ばれています。 25 00:01:45,300 --> 00:01:50,460 だから私は言う&Xときには、変数xのメモリアドレスを得ている。 26 00:01:50,460 --> 00:01:56,790 だから今は、ポインタpを持っており、どこでも私のコードで私は、* pを使用することができます 27 00:01:56,790 --> 00:02:02,960 または私はxを使用することができ、それはまったく同じものになるでしょう。 28 00:02:02,960 --> 00:02:09,520 (* p)である。これは何をやっている?あの星は何を意味するのか? 29 00:02:09,520 --> 00:02:13,120 [学生]それはその時点での値を意味します。 >>うん。 30 00:02:13,120 --> 00:02:17,590 我々はそれを見ればそう、それは図を引き出すために非常に役立つことがあります 31 00:02:17,590 --> 00:02:22,230 場合は、この値が4であることを起こるのx、、のためのメモリの箱のようだ 32 00:02:22,230 --> 00:02:25,980 次に我々は、pのメモリの小さな箱を持っている 33 00:02:25,980 --> 00:02:31,590 のでxにp個の点は、私たちはpからxへの矢印を描きます。 34 00:02:31,590 --> 00:02:40,270 だから私たちが言うとき、* pは、我々はpであるボックスに行くと言っている。 35 00:02:40,270 --> 00:02:46,480 スターは、矢印に従っており、その後、右がこのボックスに欲しいものは何でも。 36 00:02:46,480 --> 00:03:01,090 だから私は、* P = 7と言うことができます、そしてそれは、xとその7への変化であるボックスに移動します。 37 00:03:01,090 --> 00:03:13,540 または私は言うことができるint型Z = * P * 2;それは星、星ため混乱し。 38 00:03:13,540 --> 00:03:19,230 1つは、pを間接参照すると、他の星は2を乗じている。 39 00:03:19,230 --> 00:03:26,780 私はちょうど同様にxで* pを交換した可能性に注目してください。 40 00:03:26,780 --> 00:03:29,430 あなたは同じようにそれらを使用することができます。 41 00:03:29,430 --> 00:03:38,000 そして、後に、私は完全に新しいものにpポイントを持つことができます。 42 00:03:38,000 --> 00:03:42,190 私はちょうど言うことができますP = &z; 43 00:03:42,190 --> 00:03:44,940 だから今、xにはもはや点をP;それは、zを指しています。 44 00:03:44,940 --> 00:03:50,510 そして、私は* pを行う任意の時間は、それは、zを行うのと同じです。 45 00:03:50,510 --> 00:03:56,170 我々は関数になって始めると、だから、これに関する有益な事です。 46 00:03:56,170 --> 00:03:59,790 >> 何かを指し示すポインタを宣言するために無用のようなものだ 47 00:03:59,790 --> 00:04:03,140 その後、あなたはそれを間接参照している 48 00:04:03,140 --> 00:04:06,060 するときは、初めに元の変数を使用することもできました。 49 00:04:06,060 --> 00:04:18,190 しかし、あなたが関数に入るとき - それでは、我々はいくつかの関数は、int fooを持っているとしましょう 50 00:04:18,190 --> 00:04:32,810 それがポインタを取り、ちょうど* P = 6をします; 51 00:04:32,810 --> 00:04:39,990 我々はスワップと前に見たように、あなたは効果的なスワップと独立した機能を行うことはできません 52 00:04:39,990 --> 00:04:45,180 Cのすべてが常に値渡しされるため、整数だけを通過させることによって。 53 00:04:45,180 --> 00:04:48,360 あなたは値渡ししているポインタを渡している場合でも。 54 00:04:48,360 --> 00:04:51,940 それはちょうどので、それらの値がメモリアドレスであることを起こる。 55 00:04:51,940 --> 00:05:00,770 だから私は、foo(p)を言うとき、私は関数fooへのポインタを渡している 56 00:05:00,770 --> 00:05:03,910 とfooは* P = 6をやっている。 57 00:05:03,910 --> 00:05:08,600 だから内部のその関数の場合、* pがまだXに相当し、 58 00:05:08,600 --> 00:05:12,720 それは、その関数内のスコープ付きではないので、私はその関数内でxを使用することはできません。 59 00:05:12,720 --> 00:05:19,510 だから* P = 6は、私は別の関数からローカル変数にアクセスすることができる唯一の​​方法です。 60 00:05:19,510 --> 00:05:23,600 または、よく、ポインタが、私は別の関数からローカル変数にアクセスできる唯一の​​方法です。 61 00:05:23,600 --> 00:05:31,600 [学生] Let 'sは、あなたがポインタを返すしたいとしましょう​​。どのように正確にそれを行うのですか? 62 00:05:31,600 --> 00:05:44,270 [ボーデンは】int y = 3のような何かのようにポインタを返します。リターン&Y? >> [生徒]うん。 63 00:05:44,270 --> 00:05:48,480 [ボーデン]オーケー。あなたはこれを行うべきではありません。これはまずいです。 64 00:05:48,480 --> 00:05:59,480 私はあなたが、このメモリーの全体図を見始め、これらの講義のスライドで見たと思う 65 00:05:59,480 --> 00:06:02,880 ここまでは、メモリアドレス0を持っている場所 66 00:06:02,880 --> 00:06:09,550 上下ここでは32にメモリアドレス4ライブまたは2を持っています。 67 00:06:09,550 --> 00:06:15,120 だから、あなたはいくつかのものといくつかのものを持っていると、あなたはあなたのスタックを持っている 68 00:06:15,120 --> 00:06:21,780 とあなたがちょうど育っについて勉強し始めたあなたのヒープを持っている。 69 00:06:21,780 --> 00:06:24,390 [学生]はスタックの上ヒープはありませんか? 70 00:06:24,390 --> 00:06:27,760 >> うん。ヒープが上にあるではないですか? >> [生徒]まあ、彼が上に0を入れます。 71 00:06:27,760 --> 00:06:30,320 [学生]ああ、彼は上に0を入れます。 >> [生徒]ああ、大丈夫。 72 00:06:30,320 --> 00:06:36,060 免責事項:どこでもCS50とあなたはこのようにそれを参照するつもりです。 >> [生徒]オーケー。 73 00:06:36,060 --> 00:06:40,290 それは、あなたが最初のスタックを見ている時というだけです 74 00:06:40,290 --> 00:06:45,000 あなたが互いの上に物事を考えるスタッキングスタックを考えるときが好きです。 75 00:06:45,000 --> 00:06:50,810 だから我々は、スタック、スタック、通常と同じように育っているので、周りにこれを反転する傾向がある 76 00:06:50,810 --> 00:06:55,940 代わりに、スタックの下にぶら下がっている。 >> [生徒]ヒープは、技術的に、しかし、あまりにも育ちませんか? 77 00:06:55,940 --> 00:07:01,100 それはあなたが成長することによって何を意味するかに依存します。 78 00:07:01,100 --> 00:07:04,010 スタックとヒープは常に反対方向に成長します。 79 00:07:04,010 --> 00:07:09,420 スタックには、常にそれが育っているという意味で育っている 80 00:07:09,420 --> 00:07:12,940 上位のメモリアドレス、およびヒープがダウンして成長している方に 81 00:07:12,940 --> 00:07:17,260 という点では、下位のメモリアドレスに向かって成長している。 82 00:07:17,260 --> 00:07:20,250 だからトップは0であり、底はハイメモリアドレスです。 83 00:07:20,250 --> 00:07:26,390 彼らはちょうど反対方向に、成長している両方。 84 00:07:26,390 --> 00:07:29,230 [学生]あなたが底にスタックを置くと言ったので、私はちょうどそれを意味 85 00:07:29,230 --> 00:07:33,640 スタック用にヒープの先頭から開始するので、それは、より直感的なようですので、 86 00:07:33,640 --> 00:07:37,520 ヒープは、あまりにも、それ自体の上にそうthat'sだ - >>うん。 87 00:07:37,520 --> 00:07:44,960 また、より多くのようにアップすると大きいが、スタックの成長としてヒープのだと思います。 88 00:07:44,960 --> 00:07:50,280 だからスタックは、我々は一種の育って見せたいものです。 89 00:07:50,280 --> 00:07:55,390 しかし、どこでも、あなたがそうでなければ見ては、上部のアドレス0を表示しようとしている 90 00:07:55,390 --> 00:07:59,590 そして下部に最高のメモリアドレスが、これはメモリの通常のビューです。 91 00:07:59,590 --> 00:08:02,100 >> あなたは疑問を持っていますか? 92 00:08:02,100 --> 00:08:04,270 [学生]あなたは私たちにヒープについての詳細を教えていただけますか? 93 00:08:04,270 --> 00:08:06,180 うん。私は2番目のそれに得るでしょう。 94 00:08:06,180 --> 00:08:12,220 まず、&yを返す理由に戻ってことは悪いことでは、 95 00:08:12,220 --> 00:08:18,470 スタックには、すべての関数を表すスタックフレームの束を持っている 96 00:08:18,470 --> 00:08:20,460 これらは呼ばれています。 97 00:08:20,460 --> 00:08:27,990 以前の事を無視だから、あなたのスタックのトップは常にメイン機能であることを行っている 98 00:08:27,990 --> 00:08:33,090 呼び出されている最初の関数だからです。 99 00:08:33,090 --> 00:08:37,130 そして、あなたは別の関数を呼び出すときに、スタックはダウン成長しようとしている。 100 00:08:37,130 --> 00:08:41,640 私はいくつかの機能は、fooを呼び出すと、それはそれ自身のスタックフレームを取得するのであれば、 101 00:08:41,640 --> 00:08:47,280 それが、バーをいくつかの関数を呼び出すことはできますが、独自のスタックフレームを取得します。 102 00:08:47,280 --> 00:08:49,840 と、バーは再帰的であること、それは自分自身を呼び出すことができます 103 00:08:49,840 --> 00:08:54,150 などバーの2回目の呼び出しでは独自のスタックフレームを取得しようとしていること。 104 00:08:54,150 --> 00:08:58,880 そして、これらのスタックフレームに入りますので、何のローカル変数のすべてである 105 00:08:58,880 --> 00:09:03,450 その関数の引数のすべて - 106 00:09:03,450 --> 00:09:08,730 この関数のローカルスコープされているすべてのものはこれらのスタックフレームに移動します。 107 00:09:08,730 --> 00:09:21,520 だから私はバーのようなものが関数であると言った時を意味し、 108 00:09:21,520 --> 00:09:29,270 私はちょうど整数を宣言し、その整数へのポインタを返すつもりです。 109 00:09:29,270 --> 00:09:33,790 だからyはどこに住んでるんだろう? 110 00:09:33,790 --> 00:09:36,900 [学生] yはバーに住んでいます。 >> [ボーデン]うん。 111 00:09:36,900 --> 00:09:45,010 どこかでメモリのこの小さな広場にそれでyを持っているのlittlerの正方形である。 112 00:09:45,010 --> 00:09:53,370 私が戻るとyと、私はメモリのこの小さなブロックへのポインタを返すよ。 113 00:09:53,370 --> 00:09:58,400 しかし、その後、関数から戻るときは、そのスタックフレームがスタックからポップされます。 114 00:10:01,050 --> 00:10:03,530 それがスタックと呼ば​​れる理由だ。 115 00:10:03,530 --> 00:10:06,570 あなたはそれが何であるか知っていればそれは、スタックデータ構造のようなものだ。 116 00:10:06,570 --> 00:10:11,580 あるいはトレーのスタックのように常に一例であって、 117 00:10:11,580 --> 00:10:16,060 メインが下に行くつもりされている場合、あなたが最初に呼び出す関数は、その上に行くつもりです 118 00:10:16,060 --> 00:10:20,400 あなたが呼ばれてきたすべての関数から戻るまで、あなたがメインに戻って取得することはできません 119 00:10:20,400 --> 00:10:22,340 それはそれの上に置かれています。 120 00:10:22,340 --> 00:10:28,650 >> あなたは&Yを返しやった場合は、[学生]だから、その値は、予告なしに変更することがあります。 121 00:10:28,650 --> 00:10:31,290 はい、it's - >> [生徒]それは上書きされる可能性があります。 >>うん。 122 00:10:31,290 --> 00:10:34,660 それは完全です - あなたがしようとした場合 - 123 00:10:34,660 --> 00:10:38,040 それがポインタを返すだので、これはまた、int *のバーであろう 124 00:10:38,040 --> 00:10:41,310 ので、その戻り値の型はint *である。 125 00:10:41,310 --> 00:10:46,500 この関数の戻り値を使用しようとするなら、それは未定義の動作です 126 00:10:46,500 --> 00:10:51,770 そのポインタが不正なメモリを指しているからです。 >> [生徒]オーケー。 127 00:10:51,770 --> 00:11:01,250 だからどのような場合、たとえば、あなたが宣言したint型* Y =のmalloc(sizeof(int))を? 128 00:11:01,250 --> 00:11:03,740 よろしい。はい。 129 00:11:03,740 --> 00:11:07,730 [学生]私たちはごみ箱に物事をドラッグしたときに我々はどのように語ら 130 00:11:07,730 --> 00:11:11,750 それらは実際に消去していない、我々はちょうど彼らのポインタを失う。 131 00:11:11,750 --> 00:11:15,550 したがって、この場合、我々は実際にそれがメモリに残っていた値を消去するか、あるのですか? 132 00:11:15,550 --> 00:11:19,130 ほとんどの部分については、それはまだそこになるだろう。 133 00:11:19,130 --> 00:11:24,220 しかし、ここでは我々はいくつかの他の機能、bazを呼び出すことが起こるとしましょう​​。 134 00:11:24,220 --> 00:11:28,990 バズは、ここに独自のスタックフレームを取得する予定です。 135 00:11:28,990 --> 00:11:31,470 それは、このようなもののすべてを上書きすることになるだろう 136 00:11:31,470 --> 00:11:34,180 その後は、後であなたが前に持ってポインタを試してみて、使用している場合、 137 00:11:34,180 --> 00:11:35,570 それが同じ値であることを行っていない。 138 00:11:35,570 --> 00:11:38,150 それはあなたが関数bazを呼ばれるという理由だけで変​​更されたために起こっている。 139 00:11:38,150 --> 00:11:43,080 [学生]は、しかし、我々は、我々はまだ3を取得することになりませんでした? 140 00:11:43,080 --> 00:11:44,990 [ボーデン]十中八九、あなたはそうするでしょう。 141 00:11:44,990 --> 00:11:49,670 しかし、あなたはそれに頼ることはできません。 Cは単に未定義の動作を言います。 142 00:11:49,670 --> 00:11:51,920 >> [学生]ああ、それはありません。オーケー。 143 00:11:51,920 --> 00:11:58,190 mallocが使用中で出番ですから、ポインタを返すようにしたいときに、これはです。 144 00:12:00,930 --> 00:12:15,960 私は実際に書いているだけmalloc関数を返す(3 * sizeof(int))を。 145 00:12:17,360 --> 00:12:24,050 我々は、第二​​に、よりmallocの上に行くだろうが、mallocのアイデアはあなたのすべてのローカル変数 146 00:12:24,050 --> 00:12:26,760 常にスタック上に行く。 147 00:12:26,760 --> 00:12:31,570 mallocされているものは、ヒープ上に行き、それは永遠に、常にヒープ上になります 148 00:12:31,570 --> 00:12:34,490 それを明示的に解放するまで。 149 00:12:34,490 --> 00:12:42,130 だから、これはときにmallocを何かを、それは関数が戻った後に生き残るために起こっていることを意味します。 150 00:12:42,130 --> 00:12:46,800 プログラムの実行を停止した後、[学生]それが生き残るだろうか?ナンバー>> 151 00:12:46,800 --> 00:12:53,180 わかりましたので、それはプログラムがすべての方法が実行完了するまでそこになるだろう。 >>はい。 152 00:12:53,180 --> 00:12:57,510 我々は、プログラムの実行が停止したときに何が起こるかの詳細は上に行くことができます。 153 00:12:57,510 --> 00:13:02,150 あなたは私を思い出させる必要があるかもしれませんが、それはまったく別のものです。 154 00:13:02,150 --> 00:13:04,190 [学生]だから、malloc関数はポインタを作成しますか? >>うん。 155 00:13:04,190 --> 00:13:13,030 malloc関数 - >> [学生]私はmalloc関数は、ポインタが使用できるメモリのブロックを指定すると思います。 156 00:13:15,400 --> 00:13:19,610 [ボーデン]私は再びその図が欲しい。しかし>> [生徒]だからこの機能は動作しますが、? 157 00:13:19,610 --> 00:13:26,430 [学生]ええ、mallocが使用できるメモリのブロックを指定し、 158 00:13:26,430 --> 00:13:30,470 そしてそれはそのメモリの最初のブロックのアドレスを返します。 159 00:13:30,470 --> 00:13:36,750 >> [ボーデン]うん。だからときに、malloc関数は、メモリの一部のブロックをつかんでいる 160 00:13:36,750 --> 00:13:38,260 それはヒープで現在です。 161 00:13:38,260 --> 00:13:43,040 ヒープが小さすぎる場合は、ヒープだけで育つために起こっている、そしてそれはこの方向に生えています。 162 00:13:43,040 --> 00:13:44,650 それでは、ヒープが小さすぎると言うことができます。 163 00:13:44,650 --> 00:13:49,960 それは少し成長し、ちょうど育ったこのブロックへのポインタを返すようなのです。 164 00:13:49,960 --> 00:13:55,130 もし無料のものには、ヒープ内のより多くの部屋を作っているときは、 165 00:13:55,130 --> 00:14:00,030 ので、その後のmallocを呼び出すには、以前に解放されたことがそのメモリを再利用することができます。 166 00:14:00,030 --> 00:14:09,950 mallocとfreeについて重要なことは、それはあなたに完全な制御を与えるということです 167 00:14:09,950 --> 00:14:12,700 これらのメモリ·ブロックの生涯。 168 00:14:12,700 --> 00:14:15,420 グローバル変数は、常に生きている。 169 00:14:15,420 --> 00:14:18,500 ローカル変数は、その有効範囲内で生きている。 170 00:14:18,500 --> 00:14:22,140 できるだけ早くあなたが括弧を過ぎて行くように、ローカル変数は死んでいる。 171 00:14:22,140 --> 00:14:28,890 あなたはそれが生きているようにしたいときにmallocされたメモリは生きている 172 00:14:28,890 --> 00:14:33,480 あなたは解放されるということを教えたときに、その後リリースされています。 173 00:14:33,480 --> 00:14:38,420 それらは本当に、実際にメモリのわずか3種類があります。 174 00:14:38,420 --> 00:14:41,840 スタックで自動メモリ管理は、ありません。 175 00:14:41,840 --> 00:14:43,840 物事が自動的にあなたのために起こる。 176 00:14:43,840 --> 00:14:46,910 あなたがint xを言うとき、メモリはint xに対して割り当てられている。 177 00:14:46,910 --> 00:14:51,630 xがスコープの外に出ると、メモリがxに再利用されます。 178 00:14:51,630 --> 00:14:54,790 その後、動的なメモリ管理、malloc関数とは何かですが、そこ 179 00:14:54,790 --> 00:14:56,740 あなたがコントロールを持っているときにです。 180 00:14:56,740 --> 00:15:01,290 あなたは、動的にメモリを割り当てることとすべきでないかを決める。 181 00:15:01,290 --> 00:15:05,050 そして、それは永遠に生きることを意味し、静的あり 182 00:15:05,050 --> 00:15:06,610 これは、グローバル変数が何であるかです。 183 00:15:06,610 --> 00:15:10,240 彼らは、メモリ内でだけ常にね。 184 00:15:10,960 --> 00:15:12,760 >> 質問はありますか? 185 00:15:14,490 --> 00:15:17,230 [学生]は、あなただけの中括弧を使ってブロックを定義できます 186 00:15:17,230 --> 00:15:21,220 しかし、if文またはそのようなwhile文か何かを持っている持っていない? 187 00:15:21,220 --> 00:15:29,130 これは、関数のようにブロックを定義することができますが、それはあまりにも中括弧を持っています。 188 00:15:29,130 --> 00:15:32,100 [学生]だからあなたは自分のコードの中で中括弧のランダムなペアのように持つことができません 189 00:15:32,100 --> 00:15:35,680 ローカル変数を持っている? >>はい、できます。 190 00:15:35,680 --> 00:15:45,900 int型のバーの内部では{int型のy = 3;}可能性があります。 191 00:15:45,900 --> 00:15:48,440 それはここにいることになっている。 192 00:15:48,440 --> 00:15:52,450 しかし、それは完全にint型のyの範囲を定義します。 193 00:15:52,450 --> 00:15:57,320 その第二波括弧の後、yはもう使用することはできません。 194 00:15:57,910 --> 00:16:00,630 とはいえ、あなたはそれを行うことはほとんどない。 195 00:16:02,940 --> 00:16:07,370 は、プログラムが終了したときに何が起こるかに戻りましょう 196 00:16:07,370 --> 00:16:18,760 我々だけで物事を簡単にするために与えるという誤解/ハーフ嘘の種類があります。 197 00:16:18,760 --> 00:16:24,410 私たちはあなたを伝えることは、メモリを割り当てるとき 198 00:16:24,410 --> 00:16:29,860 あなたは、その変数のためにRAMの一部のチャンクを割り当てています。 199 00:16:29,860 --> 00:16:34,190 しかし、あなたは本当に直接プログラムで、これまでのRAMに触れていない。 200 00:16:34,190 --> 00:16:37,490 あなたがそれについて考える場合、どのように描きました - 201 00:16:37,490 --> 00:16:44,330 あなたは、GDBにおける通過する場合と、実際には、同じものを見ます。 202 00:16:51,120 --> 00:16:57,590 関係なく、あなたのプログラムまたは現在実行されているプログラムを実行する回数の 203 00:16:57,590 --> 00:16:59,950 スタックには、常に開始する予定です - 204 00:16:59,950 --> 00:17:06,510 あなたは、常にアドレスoxbffff何かを周りの変数を参照しようとしている。 205 00:17:06,510 --> 00:17:09,470 それはその地域のどこかに通常です。 206 00:17:09,470 --> 00:17:18,760 しかし、どのように2つのプログラム可能であれば同じメモリへのポインタを持つことができますか? 207 00:17:20,640 --> 00:17:27,650 [学生] oxbfffがRAM上にあることになっている場所のいくつかの任意の指定があります 208 00:17:27,650 --> 00:17:31,320 それは実際に関数が呼び出されたときに応じて異なる場所にすることができます。 209 00:17:31,320 --> 00:17:35,920 うん。この用語は、仮想メモリです。 210 00:17:35,920 --> 00:17:42,250 アイデアは、あなたのコンピュータ上で実行されている一つ一つのプログラムが、その一つ一つのプロセスである 211 00:17:42,250 --> 00:17:49,450 独自のを持っています - 完全に独立したアド​​レス空間 - レッツは32ビットを前提としています。 212 00:17:49,450 --> 00:17:51,590 これは、アドレス空間です。 213 00:17:51,590 --> 00:17:56,220 それは、使用するための独自の完全に独立した4ギガバイトを持っています。 214 00:17:56,220 --> 00:18:02,220 >> ですから、2つのプログラムを同時に実行した場合、このプログラムは、自身に4ギガバイトを見 215 00:18:02,220 --> 00:18:04,870 このプログラムは、自身に4ギガバイトを見 216 00:18:04,870 --> 00:18:07,720 そしてそれは、このプログラムのためにポインタを間接参照することは不可能だ 217 00:18:07,720 --> 00:18:10,920 そして、このプログラムからのメモリで終わる。 218 00:18:10,920 --> 00:18:18,200 そして、どのような仮想メモリがあると、プロセスのアドレス空間からマッピングです 219 00:18:18,200 --> 00:18:20,470 RAM上で実際のものに。 220 00:18:20,470 --> 00:18:22,940 だから、それを知るために、ご使用のオペレーティング·システムにかかっている、 221 00:18:22,940 --> 00:18:28,080 ねえ、ときに、この男は本当に意味ポインタ逆参照oxbfffを、 222 00:18:28,080 --> 00:18:31,040 彼はRAMバイト1000、望んでいる 223 00:18:31,040 --> 00:18:38,150 一方、このプログラムを逆参照のoxbfffば、彼は本当にRAMバイト万を望んでいる。 224 00:18:38,150 --> 00:18:41,590 彼らは遠く離れて勝手にすることができます。 225 00:18:41,590 --> 00:18:48,730 これは、単一のプロセスのアドレス空間内であっても物事の真実である。 226 00:18:48,730 --> 00:18:54,770 のようにそれ自体にすべての4ギガバイトが表示されますが、言ってみましょう - 227 00:18:54,770 --> 00:18:57,290 [学生]一つ一つのプロセスをしない - 228 00:18:57,290 --> 00:19:01,350 Let 'sは、あなたがRAMしか4ギガバイトを搭載したコンピュータを持っていると言う。 229 00:19:01,350 --> 00:19:06,430 一つ一つのプロセスは全体4ギガバイトを参照していますか? >>はい。 230 00:19:06,430 --> 00:19:13,060 しかし、それは見て4ギガバイトは嘘です。 231 00:19:13,060 --> 00:19:20,460 それはちょうど、それは、他のプロセスが存在することを知っていないので、それがすべてこのメモリを持っていると思っている。 232 00:19:20,460 --> 00:19:28,140 それは実際に必要なだけ多くのメモリを使用します。 233 00:19:28,140 --> 00:19:32,340 オペレーティング·システムは、このプロセスにRAMを提供するつもりされていません 234 00:19:32,340 --> 00:19:35,750 それは、この地域全体の任意のメモリを使用していない場合。 235 00:19:35,750 --> 00:19:39,300 それはそれに、その領域のためのメモリを与えることはないだろう。 236 00:19:39,300 --> 00:19:54,780 しかし、アイデアはある - 私は考えるようにしようとしている - 私はアナロジーを考えることはできません。 237 00:19:54,780 --> 00:19:56,780 アナロジーは難しいです。 238 00:19:57,740 --> 00:20:02,700 仮想メモリの問題の一つまたはそれが解決だことの一つ 239 00:20:02,700 --> 00:20:06,810 プロセスが互いに完全に気づかなければならないということです。 240 00:20:06,810 --> 00:20:12,140 そしてあなたは、それだけで、任意のポインタ逆参照する任意のプログラムを書くことができます 241 00:20:12,140 --> 00:20:19,340 ただ、*(ox1234)と言うプログラムを書きたい 242 00:20:19,340 --> 00:20:22,890 そしてその逆参照のメモリアドレス1234。 243 00:20:22,890 --> 00:20:28,870 >> しかし、それは次に何1234手段を翻訳するために、オペレーティング·システムにお任せします。 244 00:20:28,870 --> 00:20:33,960 もしそうなら1234は、このプロセスのために有効なメモリアドレスであることを起こる 245 00:20:33,960 --> 00:20:38,800 それはスタックまたは何か上にあるように、これはそのメモリアドレスの値を返します 246 00:20:38,800 --> 00:20:41,960 限りプロセスが知っている。 247 00:20:41,960 --> 00:20:47,520 しかし、それが土地を起こるように1234は、有効なアドレスではない場合、 248 00:20:47,520 --> 00:20:52,910 スタックを超えていますここでメモリのいくつかの小さな作品とヒープを超え 249 00:20:52,910 --> 00:20:57,200 あなたがセグメンテーション違反のようなものを取得するときに、あなたが本当にそれを使用していないが、その後、それはだ 250 00:20:57,200 --> 00:21:00,260 あなたは触れてはならないことを記憶に触れているので。 251 00:21:07,180 --> 00:21:09,340 また、これは本当です - 252 00:21:09,340 --> 00:21:15,440 32ビットシステムで、32ビットを使用すると、メモリアドレスを定義するには、32ビットを持っていることを意味します。 253 00:21:15,440 --> 00:21:22,970 または4バイト - 32ビットは8バイトなので、ポインタは8バイトである理由です。 254 00:21:22,970 --> 00:21:25,250 ポインタは4バイトです。 255 00:21:25,250 --> 00:21:33,680 ですからoxbfffffようなポインタを参照するとき、それはです - 256 00:21:33,680 --> 00:21:40,080 あなただけの、任意のポインタを作成することができます任意のプログラム内 257 00:21:40,080 --> 00:21:46,330 どこox0から牛8 f'sへ - FFFFFFFF。 258 00:21:46,330 --> 00:21:49,180 [学生]あなたは彼らが4バイトだと言ったではありませんか>>うん。 259 00:21:49,180 --> 00:21:52,730 [学生]それから各バイトがあります - >> [ボーデン] 16進数。 260 00:21:52,730 --> 00:21:59,360 16進数 - 5、6、7、8。ポインタので、常に16進数で表示するつもりだ。 261 00:21:59,360 --> 00:22:01,710 それは、我々はポインタを分類する方法だけです。 262 00:22:01,710 --> 00:22:05,240 進数の各2桁が1バイトです。 263 00:22:05,240 --> 00:22:09,600 だから4バイトの8桁の16進数があるように起こっている。 264 00:22:09,600 --> 00:22:14,190 だから、32ビットシステム上のすべての単一のポインタは4バイトであることを行っている 265 00:22:14,190 --> 00:22:18,550 それはあなたのプロセスでは、任意の4バイトを構築することができることを意味します 266 00:22:18,550 --> 00:22:20,550 そして、それのポインタを作る 267 00:22:20,550 --> 00:22:32,730 これは、限り、それは認識してだとして、それがメモリの32バイト全体の2に対処できることを意味します。 268 00:22:32,730 --> 00:22:34,760 それは実際にへのアクセス権を持っていなくても、 269 00:22:34,760 --> 00:22:40,190 お使いのコンピュータにのみ512メガバイトを持っている場合でも、それはそれは多くのメモリを持っていると考えている。 270 00:22:40,190 --> 00:22:44,930 およびオペレーティング·システムはそれだけで、あなたが実際に必要なものを割り当てるように十分スマートです。 271 00:22:44,930 --> 00:22:49,630 4ライブ:それはちょうど、ああ、新しいプロセスを行っておりません。 272 00:22:49,630 --> 00:22:51,930 >> うん。 >> [生徒] oxはどういう意味ですか?なぜあなたはそれを書くのですか? 273 00:22:51,930 --> 00:22:54,980 それはちょうど進のためのシンボルです。 274 00:22:54,980 --> 00:22:59,590 あなたは牛と番号の開始を参照してくださいすると、連続したものは16進数です。 275 00:23:01,930 --> 00:23:05,760 [学生]あなたは、プログラムの終了時に何が起こるかについて説明しました。 >>はい。 276 00:23:05,760 --> 00:23:09,480 どのようなプログラムが終了したときに起こることは、オペレーティング·システムです 277 00:23:09,480 --> 00:23:13,600 ただ消去し、それがこれらのアドレスを持っていることをマッピングし、それだ。 278 00:23:13,600 --> 00:23:17,770 オペレーティングシステムは今ちょうど使用する別のプログラムにそのメモリを与えることができます。 279 00:23:17,770 --> 00:23:19,490 [学生]オーケー。 280 00:23:19,490 --> 00:23:24,800 ですから、ヒープまたはスタックまたはグローバル変数か何かで何かを割り当てるときに、 281 00:23:24,800 --> 00:23:27,010 それらはすべて同じようにすぐにプログラムが終了すると消えてしまう 282 00:23:27,010 --> 00:23:32,120 オペレーティングシステムは現在、他のプロセスにそのメモリを与えるために自由であるためです。 283 00:23:32,120 --> 00:23:35,150 [学生]で記述された値は、おそらくまだあるにもかかわらず? >>うん。 284 00:23:35,150 --> 00:23:37,740 値はまだありそうです。 285 00:23:37,740 --> 00:23:41,570 それはちょうどそれは、それらを取得することは困難になるだろうだ。 286 00:23:41,570 --> 00:23:45,230 それが削除されたファイルを取得するよりも、それは彼らを得るためにはるかに困難だ 287 00:23:45,230 --> 00:23:51,450 削除されたファイルの種類のは、長い時間のためにそこに座って、ハードドライブがはるかに大きいからです。 288 00:23:51,450 --> 00:23:54,120 だからそれはメモリのさまざまな部分を上書きするために起こっている 289 00:23:54,120 --> 00:23:58,640 それは、そのファイルがにあったことをメモリチャンクを上書きする起こる前。 290 00:23:58,640 --> 00:24:04,520 しかし、メインメモリ、RAM、かなり速くを通してあなたのサイクルを、 291 00:24:04,520 --> 00:24:08,040 ので、非常に急速に上書きになるだろう。 292 00:24:10,300 --> 00:24:13,340 このまたは他の何かについての質問? 293 00:24:13,340 --> 00:24:16,130 [学生]私は別のトピックについての質問があります。オーケー。>> 294 00:24:16,130 --> 00:24:19,060 誰もがこれについて質問がありますか? 295 00:24:20,170 --> 00:24:23,120 >> オーケー。別の話題。 >> [生徒]オーケー。 296 00:24:23,120 --> 00:24:26,550 私は、模擬試験の一部を通過した 297 00:24:26,550 --> 00:24:30,480 そのうちの一つには、sizeofについて話していた 298 00:24:30,480 --> 00:24:35,630 それは変数の型を返すか、または異なっていること、および値。 >>はい。 299 00:24:35,630 --> 00:24:45,060 そしてそれは、intとlong両方のリターン4の両方と言ったので、彼らは両方とも4バイト長だ。 300 00:24:45,060 --> 00:24:48,070 intとlongの間に違いはありますか、またはそれは同じことですか? 301 00:24:48,070 --> 00:24:50,380 はい、違いがあります。 302 00:24:50,380 --> 00:24:52,960 C標準 - 303 00:24:52,960 --> 00:24:54,950 私はおそらく台無しにするつもりです。 304 00:24:54,950 --> 00:24:58,800 C標準では、C言語が何であるかをCの公式ドキュメントを同様です 305 00:24:58,800 --> 00:25:00,340 これは、言っていることです。 306 00:25:00,340 --> 00:25:08,650 だから、C標準では、単にcharは永遠に、常に1バイトだろう、と話している。 307 00:25:10,470 --> 00:25:19,040 後のすべて - 短期は常にちょうどより大きいまたはcharに等しいものとして定義されています。 308 00:25:19,040 --> 00:25:23,010 これは厳密にはより大きいが、肯定的ではないかもしれません。 309 00:25:23,010 --> 00:25:31,940 intはちょうどより大きいか、またはショートに等しいものとして定義されています。 310 00:25:31,940 --> 00:25:36,210 と長いだけより大きいまたはintに等しいものとして定義されています。 311 00:25:36,210 --> 00:25:41,600 とlong longより大きいか、または長いと等しくなります。 312 00:25:41,600 --> 00:25:46,610 だから、C標準で定義されて唯一のものは、すべてのものの相対的な順序です。 313 00:25:46,610 --> 00:25:54,880 物事は取ることを実際のメモリ量は、最大実装に一般的であり、 314 00:25:54,880 --> 00:25:57,640 しかし、それはかなりよく、この時点で定義されている。 >> [生徒]オーケー。 315 00:25:57,640 --> 00:26:02,490 だからパンツはほとんど常に2バイトになるだろうしている。 316 00:26:04,920 --> 00:26:09,950 int型はほとんど常に4バイトになるだろうしている。 317 00:26:12,070 --> 00:26:15,340 ロングlong型は、ほとんど常に8バイトになるだろうしている。 318 00:26:17,990 --> 00:26:23,160 そして、それはあなたが32ビットまたは64ビットのシステムを使用しているかどうかに依存し、待ち望んでいます。 319 00:26:23,160 --> 00:26:27,450 だから長くは、システムのタイプに対応する予定です。 320 00:26:27,450 --> 00:26:31,920 あなたがアプライアンスのように32ビットシステムを使用している場合は、それが4バイトになるだろう。 321 00:26:34,530 --> 00:26:42,570 あなたは、最近のコンピュータの多くのように64ビットを使用している場合、それは8バイトになるだろう。 322 00:26:42,570 --> 00:26:45,230 >> int型はほとんど常にこの時点では4バイトです。 323 00:26:45,230 --> 00:26:47,140 ロングlong型は、ほとんど常に8バイトです。 324 00:26:47,140 --> 00:26:50,300 過去では、intは2バイトになるように使用されます。 325 00:26:50,300 --> 00:26:56,840 しかし、これは完全に超え、それに等しいこれらの関係のすべてを満たしていることがわかります。 326 00:26:56,840 --> 00:27:01,280 だから長い完全に整数と同じサイズであることが許され、 327 00:27:01,280 --> 00:27:04,030 そしてそれはまた長い長いと同じサイズになるように許可されている。 328 00:27:04,030 --> 00:27:11,070 そして、それはちょうどので、システムの99.999%で、それが等しくなるように起こっていることであることを起こる 329 00:27:11,070 --> 00:27:15,800 intやlong longのいずれか。それはちょうど32ビットまたは64ビットに依存します。 >> [生徒]オーケー。 330 00:27:15,800 --> 00:27:24,600 山車では、どのように小数点がビットに関して指定されている? 331 00:27:24,600 --> 00:27:27,160 バイナリとして好きですか? >>うん。 332 00:27:27,160 --> 00:27:30,570 あなたはCS50のためにそれを知っている必要はありません。 333 00:27:30,570 --> 00:27:32,960 あなたも61にすることを学ぶことはありません。 334 00:27:32,960 --> 00:27:37,350 あなたはどのコースにも、本当に学ぶことはありません。 335 00:27:37,350 --> 00:27:42,740 それはただの表現だ。 336 00:27:42,740 --> 00:27:45,440 私は正確なビット割り当てを忘れる。 337 00:27:45,440 --> 00:27:53,380 浮動小数点の考え方は、表現するために特定のビット数を割り当てることである - 338 00:27:53,380 --> 00:27:56,550 基本的に、すべてが科学表記法である。 339 00:27:56,550 --> 00:28:05,600 それで、あなたは1.2345のように、数そのものを表すために特定のビット数を割り当てる。 340 00:28:05,600 --> 00:28:10,200 私は5より大きい桁の数を表すことはできません。 341 00:28:12,200 --> 00:28:26,300 それは次のようになる傾向があるように、あなたはまた、特定のビット数を割り当てる 342 00:28:26,300 --> 00:28:32,810 あなただけが持つことができる最大の指数だと同じように特定の数、に上がることができます 343 00:28:32,810 --> 00:28:36,190 そしてあなただけの、特定の指数にまで行くことができます 344 00:28:36,190 --> 00:28:38,770 そのようにあなたが持つことができる最小の指数です。 345 00:28:38,770 --> 00:28:44,410 >> 私はビットはこれらの値のすべてに割り当てられている正確な方法を、覚えていない 346 00:28:44,410 --> 00:28:47,940 しかし、特定のビット数は、1.2345に専念しています 347 00:28:47,940 --> 00:28:50,930 ビットの別の特定の数は、指数に専念しています 348 00:28:50,930 --> 00:28:55,670 そして、それはある程度の大きさの指数を表すためだけに可能です。 349 00:28:55,670 --> 00:29:01,100 [学生]そして二重?それは余分な長いフロートのようなものです? >>うん。 350 00:29:01,100 --> 00:29:07,940 それは今あなたが8バイトの代わりに4バイトを使用している除くfloatと同じことだ。 351 00:29:07,940 --> 00:29:11,960 今、あなたは、9桁または10桁の数字を使用することができるでしょう 352 00:29:11,960 --> 00:29:16,630 これは300の代わりに100まで行くことができるようになります。 >> [生徒]オーケー。 353 00:29:16,630 --> 00:29:21,550 や山車も4バイトです。 >>はい。 354 00:29:21,550 --> 00:29:27,520 さて、再び、それはおそらく、一般的な実装上の全体的な依存 355 00:29:27,520 --> 00:29:30,610 しかしフロートは4バイト、doubleは8です。 356 00:29:30,610 --> 00:29:33,440 彼らは二重フロートの大きさなので、ダブルはダブルと呼ばれています。 357 00:29:33,440 --> 00:29:38,380 [学生]オーケー。そしてそこには、二倍にされますか? >>まったくありません。 358 00:29:38,380 --> 00:29:43,660 私は思う - 長いlong型と同様>> [生徒]? >>うん。私はそうは思わない。はい。 359 00:29:43,660 --> 00:29:45,950 [学生]昨年のテストでは、main関数についての質問があった 360 00:29:45,950 --> 00:29:49,490 あなたのプログラムの一部にならなくて。 361 00:29:49,490 --> 00:29:52,310 その答えは、あなたのプログラムの一部である必要はありませんということでした。 362 00:29:52,310 --> 00:29:55,100 どんな状況で?それは私が見たものだ。 363 00:29:55,100 --> 00:29:59,090 [ボーデン]それはだ - >> [生徒]何の状況? 364 00:29:59,090 --> 00:30:02,880 あなたは問題を持っていますか? >> [生徒]ええ、私は間違いなくそれを引き出すことができます。 365 00:30:02,880 --> 00:30:07,910 それは技術的には、なくてもかまいませんが、基本的にはなるだろう。 366 00:30:07,910 --> 00:30:10,030 [学生]私は別の年の上の1つを見た。 367 00:30:10,030 --> 00:30:16,220 これは、TrueまたはFalseのようだった:有効 - >>ああ、cファイル。? 368 00:30:16,220 --> 00:30:18,790 [学生]任意のCファイルが持っている必要があります - [一度に話すの両方 - 不明朗] 369 00:30:18,790 --> 00:30:21,120 オーケー。だからそれは別だ。 370 00:30:21,120 --> 00:30:26,800 >> cファイルはただの関数を含める必要があります。 371 00:30:26,800 --> 00:30:32,400 あなたは、マシンコードにバイナリをファイルをコンパイルすることができ、何でも、 372 00:30:32,400 --> 00:30:36,620 まだそれは実行可能であることなし。 373 00:30:36,620 --> 00:30:39,420 有効な実行は、main関数を持っている必要があります。 374 00:30:39,420 --> 00:30:45,460 あなたは、100 1ファイル内の関数はありませんが、メインを書くことができます 375 00:30:45,460 --> 00:30:48,800 して、その下にバイナリにコンパイル、 376 00:30:48,800 --> 00:30:54,460 その後は本体のみ持っていますが、それはこれらの機能の束を呼び出して別のファイルを書き込む 377 00:30:54,460 --> 00:30:56,720 こっちにこのバイナリファイルに保存されます。 378 00:30:56,720 --> 00:31:01,240 実行可​​能ファイルを作っているときなど、それはリンカが何をするかだ 379 00:31:01,240 --> 00:31:05,960 それは実行可能ファイルにこれらの2つのバイナリファイルを結合しています。 380 00:31:05,960 --> 00:31:11,400 だからcファイルはまったくmain関数を持っている必要はありません。 381 00:31:11,400 --> 00:31:19,220 と大きなコードベース上では、cファイルと1つの主要なファイルの数千が表示されます。 382 00:31:23,960 --> 00:31:26,110 多くの質問? 383 00:31:29,310 --> 00:31:31,940 [学生]別の質問がありました。 384 00:31:31,940 --> 00:31:36,710 これは、makeがコンパイラであると述べた。真か偽か 385 00:31:36,710 --> 00:31:42,030 と答えが偽であった、そしてそれはClangのようではありませんなぜ私が理解した。 386 00:31:42,030 --> 00:31:44,770 しかし、我々はそれがない場合は、確認を何というでしょうか? 387 00:31:44,770 --> 00:31:49,990 メイクは基本的にある - 私はそれを呼び出すかを正確に確認することができます。 388 00:31:49,990 --> 00:31:52,410 しかし、それだけでコマンドを実行します。 389 00:31:53,650 --> 00:31:55,650 ことを確認します。 390 00:31:58,240 --> 00:32:00,870 私は、このプルアップすることができます。うん。 391 00:32:10,110 --> 00:32:13,180 ああ、うん。またことがないことを確認してください。 392 00:32:13,180 --> 00:32:17,170 これは、makeユーティリティの目的は自動的に決定することであると言う 393 00:32:17,170 --> 00:32:19,610 大規模なプログラムの中には、再コンパイルする必要があるもの 394 00:32:19,610 --> 00:32:22,350 し、それらをコンパイルするためのコマンドを発行します。 395 00:32:22,350 --> 00:32:27,690 あなたは絶対に巨大なファイルを作ることができます。 396 00:32:27,690 --> 00:32:33,210 メイクは、私たちが前に言ったように、ファイルのタイムスタンプを見て、 397 00:32:33,210 --> 00:32:36,930 あなたがダウンして、個々のファイルをコンパイルすることができます、あなたがリンカに到達するまで、そうではありません 398 00:32:36,930 --> 00:32:39,270 彼らは、実行可能ファイルに一緒に入れているという。 399 00:32:39,270 --> 00:32:43,810 ですから、10種類のファイルがあり、あなたがそれらの1に変更を加えた場合、 400 00:32:43,810 --> 00:32:47,870 次に何を作るには何をしようとしていると、1ファイルだけを再コンパイルすることである 401 00:32:47,870 --> 00:32:50,640 その後一緒にすべてを再リンクします。 402 00:32:50,640 --> 00:32:53,020 しかし、それはそれよりはるかに愚かだ。 403 00:32:53,020 --> 00:32:55,690 それは完全にそれはそれは何をすべきかということを定義するのはあなた次第です。 404 00:32:55,690 --> 00:32:59,560 これはデフォルトでは、このタイムスタンプのものを認識する能力を持っている 405 00:32:59,560 --> 00:33:03,220 しかし、あなたは何もするmakeファイルを書き込むことができます。 406 00:33:03,220 --> 00:33:09,150 あなたはそれだけで別のディレクトリにCDの作る入力したときになるように作るファイルを書き込むことができます。 407 00:33:09,150 --> 00:33:15,560 私はイライラしました私はタックすべて私のアプライアンスの内側にあるため 408 00:33:15,560 --> 00:33:21,740 そして私はMacからPDFを表示。 409 00:33:21,740 --> 00:33:30,720 >> だから私は、Finderに行くと私は移動を行うことができますが、サーバーへの接続、 410 00:33:30,720 --> 00:33:36,950 と私はサーバーへの接続は私のアプライアンスであり、その後、私は、PDFを開く 411 00:33:36,950 --> 00:33:40,190 それは、LaTeXでコンパイルされます。 412 00:33:40,190 --> 00:33:49,320 毎回私はPDFファイルをリフレッシュする必要がありましたので、私は不満になっていた、 413 00:33:49,320 --> 00:33:53,900 私はそれがアクセスできる特定のディレクトリにコピーする必要がありました 414 00:33:53,900 --> 00:33:57,710 そしてそれは迷惑になっていた。 415 00:33:57,710 --> 00:34:02,650 だから代わりに私はあなたがそれは、物事を行う方法を定義する必要がmakeファイルを書いた。 416 00:34:02,650 --> 00:34:06,130 どのようにこのようにすると、PDFラテックスである。 417 00:34:06,130 --> 00:34:10,090 ただ、他のmakeファイルのように - または私はあなたが作るファイルを見ていないと思いますが、 418 00:34:10,090 --> 00:34:13,510 しかし、我々は、アプライアンスにだけ言うグローバルmakeファイルを持っている 419 00:34:13,510 --> 00:34:16,679 あなたがCファイルをコンパイルしている場合、Clangのを使用しています。 420 00:34:16,679 --> 00:34:20,960 ので、ここで私のmakeファイルで私が言わせること、 421 00:34:20,960 --> 00:34:25,020 このファイルは、PDF LaTeXでコンパイルするつもりだ。 422 00:34:25,020 --> 00:34:27,889 そしてそれはコンパイルをやってPDFをLaTeXのだ。 423 00:34:27,889 --> 00:34:31,880 makeはコンパイルされていません。それはちょうど私が指定された順序でこれらのコマンドを実行している。 424 00:34:31,880 --> 00:34:36,110 だから、それは私はそれがにコピーしたいディレクトリにコピーし、PDF形式にLaTeXを、それを実行します 425 00:34:36,110 --> 00:34:38,270 それは、CDのディレクトリに、他のことを行っていて、 426 00:34:38,270 --> 00:34:42,380 しかし、それはないすべては、ときに、ファイルの変更を認識している 427 00:34:42,380 --> 00:34:45,489 それが変更された場合と、それはそれが実行するはずのコマンドを実行します 428 00:34:45,489 --> 00:34:48,760 ときに、ファイルが変更されます。 >> [生徒]オーケー。 429 00:34:50,510 --> 00:34:54,420 私はグローバルなメークファイルは、私はそれをチェックアウトするためのものか分からない。 430 00:34:57,210 --> 00:35:04,290 その他の質問は?過去から何クイズ?任意のポインタもの? 431 00:35:06,200 --> 00:35:08,730 のようなポインタを持つ微妙なものがあります - 432 00:35:08,730 --> 00:35:10,220 私はそれにクイズの質問を見つけることができるようにするつもりはない - 433 00:35:10,220 --> 00:35:16,250 しかし、ちょうどこのようなもののような。 434 00:35:19,680 --> 00:35:24,060 私が言うとき、あなたがそれを理解していることを確認します。int * x * yを - 435 00:35:24,890 --> 00:35:28,130 これは、まさにここに何もないですが、私は推測する。 436 00:35:28,130 --> 00:35:32,140 しかし、のような* x * yを、それらがスタック上にある2つの変数があります。 437 00:35:32,140 --> 00:35:37,220 私が言うと、x =のmalloc(sizeof(int))を、xは、まだスタック上の変数である 438 00:35:37,220 --> 00:35:41,180 malloc関数は、ヒープ内でいくつかのブロックであり、我々は、ヒープにX点を抱えている。 439 00:35:41,180 --> 00:35:43,900 >> ヒープにスタックポイントで何かそう。 440 00:35:43,900 --> 00:35:48,100 たびにmallocの何かを、あなたは必然的にポインタの中にそれを保存している。 441 00:35:48,100 --> 00:35:55,940 そのポインタがスタック上にあるように、mallocされたブロックは、ヒープ上にある。 442 00:35:55,940 --> 00:36:01,240 多くの人が混乱と言うint型* X = malloc関数であり、xは、ヒープ上にある。 443 00:36:01,240 --> 00:36:04,100 xが指す何号は、ヒープ上にある。 444 00:36:04,100 --> 00:36:08,540 何らかの理由であなたは、xがグローバル変数でなければしていない限り、X自体は、スタック上にある 445 00:36:08,540 --> 00:36:11,960 その場合、それはメモリの別の領域にあることを起こる。 446 00:36:13,450 --> 00:36:20,820 を追跡するので、これらのボックスと矢印の図は、クイズのために非常によく見られます。 447 00:36:20,820 --> 00:36:25,740 それはクイズ0ではない場合、または、それはクイズ1日になるでしょう。 448 00:36:27,570 --> 00:36:31,940 あなたはこれらのすべては、コンパイルの手順を知っておくべきこと 449 00:36:31,940 --> 00:36:35,740 あなたはそれらの質問に答えなければならなかったので。はい。 450 00:36:35,740 --> 00:36:38,940 [学生]は、我々は、それらのステップ上に行くでした - >>確かに。 451 00:36:48,340 --> 00:36:58,640 手順とコンパイルする前に、我々は、前処理を持た 452 00:36:58,640 --> 00:37:16,750 コンパイル、アセンブル、リンクします。 453 00:37:16,750 --> 00:37:21,480 前処理。それは何をしますか? 454 00:37:29,720 --> 00:37:32,290 それはで最も簡単なステップです - まあ、しないように - 455 00:37:32,290 --> 00:37:35,770 それはそれは明白であるべきという意味ではありませんが、それは簡単なステップです。 456 00:37:35,770 --> 00:37:38,410 あなたたちはそれを自分自身を実装することができます。うん。 457 00:37:38,410 --> 00:37:43,410 [学生]は、あなたの持っているものを取るこのように含まれており、それがコピーしても定義されています。 458 00:37:43,410 --> 00:37:49,250 それは、#includeのようなものを探して#define 459 00:37:49,250 --> 00:37:53,800 それらが実際に何を意味するのか、それだけでコピーとペースト。 460 00:37:53,800 --> 00:37:59,240 ですから、#cs50.hを含めると言うとき、プリプロセッサはcs50.hをコピー&ペーストされている 461 00:37:59,240 --> 00:38:01,030 その行に。 462 00:38:01,030 --> 00:38:06,640 あなたは第4位であるxを定義すると言う場合、プリプロセッサは、プログラム全体を通過 463 00:38:06,640 --> 00:38:10,400 及び4 xのすべてのインスタンスを置き換えます。 464 00:38:10,400 --> 00:38:17,530 だから、プリプロセッサは、有効なCファイルを受け取り、有効なCファイルを出力 465 00:38:17,530 --> 00:38:20,300 どこのものがコピーされ、貼り付けられています。 466 00:38:20,300 --> 00:38:24,230 だから今コンパイル。それは何をしますか? 467 00:38:25,940 --> 00:38:28,210 [学生]これはC言語からバイナリへ行く。 468 00:38:28,210 --> 00:38:30,970 >> [ボーデン]それはバイナリにすべての道を行くことはありません。 469 00:38:30,970 --> 00:38:34,220 マシンコードにして、[学生]? >>それはマシンコードではありません。 470 00:38:34,220 --> 00:38:35,700 [学生]総会は? >>アセンブリ。 471 00:38:35,700 --> 00:38:38,890 それはCコードへのすべての道を行く前に、それは、国会に行く 472 00:38:38,890 --> 00:38:45,010 ほとんどの言語ではこのような何かを。 473 00:38:47,740 --> 00:38:50,590 任意の高水準言語を選んで、あなたはそれをコンパイルするつもりなら、 474 00:38:50,590 --> 00:38:52,390 それはステップでコンパイルすることがありそうです。 475 00:38:52,390 --> 00:38:58,140 最初にそれがCにPythonをコンパイルしようとしている、それは、国会にCをコンパイルするために起こっている 476 00:38:58,140 --> 00:39:01,600 [アセンブリをバイナリに変換されるとしている。 477 00:39:01,600 --> 00:39:07,800 だからコンパイルは、Cからアセンブリにそれを持って来るために起こっている。 478 00:39:07,800 --> 00:39:12,130 コンパイルという言葉は、通常より高いレベルからそれを持って来ることを意味し 479 00:39:12,130 --> 00:39:14,340 低レベルのプログラミング言語へ。 480 00:39:14,340 --> 00:39:19,190 ですから、これは高レベルの言語で始まるコンパイルで唯一のステップです 481 00:39:19,190 --> 00:39:23,270 と低水準言語で終わる、とステップはコンパイルと呼ばれる理由です。 482 00:39:25,280 --> 00:39:33,370 コンパイル時に、[学生]は、あなたが#includeをやったと言ってみましょうcs50.h. 483 00:39:33,370 --> 00:39:42,190 コンパイラは、そこにある関数と同様に、cs50.hを再コンパイルします 484 00:39:42,190 --> 00:39:45,280 そして、同様にそのアセンブリコードに変換 485 00:39:45,280 --> 00:39:50,830 またはそれは、事前に組み立ててきている何かをコピーして貼り付けるのでしょうか? 486 00:39:50,830 --> 00:39:56,910 cs50.hはかなり議会で終わることは決してありません。 487 00:39:59,740 --> 00:40:03,680 関数プロトタイプや物事のようなものはあなたが注意するだけのためのものです。 488 00:40:03,680 --> 00:40:09,270 これは、コンパイラがあなたのようなものが関数を呼び出して確認することが保証され 489 00:40:09,270 --> 00:40:12,910 右の戻り値の型、右引数やものに。 490 00:40:12,910 --> 00:40:18,350 >> だからcs50.hはファイルに前処理されます、そして、次に、それはコンパイルしているとき 491 00:40:18,350 --> 00:40:22,310 それはすべてが正しく呼び出されていることを確認して落札後は基本的に捨てている。 492 00:40:22,310 --> 00:40:29,410 cs50.hから分離されているCS50ライブラリで定義されているが、関数、 493 00:40:29,410 --> 00:40:33,610 それらは別々にコンパイルされません。 494 00:40:33,610 --> 00:40:37,270 それは実際にリンクステップで降りてくるの​​で、我々は、第二​​に、それを取得します。 495 00:40:37,270 --> 00:40:40,100 しかし、最初に、組み立ては何ですか? 496 00:40:41,850 --> 00:40:44,500 [学生]バイナリへのアセンブリ? >>うん。 497 00:40:46,300 --> 00:40:48,190 組み立て。 498 00:40:48,190 --> 00:40:54,710 組立はかなりの純粋なバイナリ変換したものですので、我々はそれがコンパイル呼び出すことはありません。 499 00:40:54,710 --> 00:41:00,230 アセンブリからバイナリへ行くにはほとんどロジックがあります。 500 00:41:00,230 --> 00:41:03,180 それはちょうどテーブルの検索のようなものだ、ああ、私たちはこの命令を持っています。 501 00:41:03,180 --> 00:41:06,290 それはバイナリ01110に対応しています。 502 00:41:10,200 --> 00:41:15,230 一般的に出力がされています。oファイルをアセンブルするファイルそう。 503 00:41:15,230 --> 00:41:19,020 と。oファイルは、我々が前に言っていたものですが、 504 00:41:19,020 --> 00:41:21,570 どのファイルがmain関数を持っている必要はありません。 505 00:41:21,570 --> 00:41:27,640 それは有効なCのファイルだとして任意のファイルであればoファイルにコンパイルすることができます。 506 00:41:27,640 --> 00:41:30,300 それは、Oにコンパイルすることができます。 507 00:41:30,300 --> 00:41:43,030 さて、リンクは実際の束をもたらすものoファイルであり、実行可能ファイルにそれらをもたらす。 508 00:41:43,030 --> 00:41:51,110 それで何のリンクがないと、あなたは。oファイルとしてCS50ライブラリと考えることができています。 509 00:41:51,110 --> 00:41:56,980 それは、すでにコンパイルされたバイナリファイルです。 510 00:41:56,980 --> 00:42:03,530 それで、あなたはあなたのファイルをコンパイルするときに、GetStringメソッド呼び出しあなたのhello.cを、 511 00:42:03,530 --> 00:42:06,360 hello.oにコンパイルhello.cを取得し、 512 00:42:06,360 --> 00:42:08,910 hello.oはバイナリになりました。 513 00:42:08,910 --> 00:42:12,830 、それは、GetStringを使用しているので、cs50.oの所へ行く必要がある 514 00:42:12,830 --> 00:42:16,390 とリンカはそれらを一緒にsmooshes、このファイルにGetStringをコピー 515 00:42:16,390 --> 00:42:20,640 それが必要なすべての機能を持って実行可能で出てくる。 516 00:42:20,640 --> 00:42:32,620 だからcs50.oは実際にOファイルではありませんが、それは根本的な違いがないことを十分に近いです。 517 00:42:32,620 --> 00:42:36,880 だからリンクは一緒にファイルの束を持って来る 518 00:42:36,880 --> 00:42:41,390 それは別に私が使用する必要があるすべての関数が含まれている 519 00:42:41,390 --> 00:42:46,120 と、実際に実行され、実行可能ファイルを作成します。 520 00:42:48,420 --> 00:42:50,780 >> そしてそうそれは我々が前に言っていたものでもあり 521 00:42:50,780 --> 00:42:55,970 あなたは1000年を持つことができる場所。cファイルを、あなたは、それらすべてをコンパイルしますoファイルは、 522 00:42:55,970 --> 00:43:00,040 おそらく、しばらく時間がかかるとなる、その後は1に変更します。cファイル。 523 00:43:00,040 --> 00:43:05,480 あなたは、その1 cファイルをコンパイルしてから、他のすべてを再リンクする必要があり、 524 00:43:05,480 --> 00:43:07,690 戻って一緒にすべてのものをリンクします。 525 00:43:09,580 --> 00:43:11,430 我々はlcs50を書くリンクしている[学生]? 526 00:43:11,430 --> 00:43:20,510 うん、いわゆるlcs50。あなたがそのライブラリにリンクする必要があることをリンカにそのフラグ信号。 527 00:43:26,680 --> 00:43:28,910 質問はありますか? 528 00:43:41,310 --> 00:43:46,860 我々は最初の講義で、その5秒以外のバイナリを検討してきました? 529 00:43:50,130 --> 00:43:53,010 私はそうは思わない。 530 00:43:55,530 --> 00:43:58,820 あなたは、私たちが見てきましたことは大きなOSのすべてを知っている必要があり、 531 00:43:58,820 --> 00:44:02,670 私たちはあなたに関数を与えた場合、あなたは、することができるはず 532 00:44:02,670 --> 00:44:09,410 あなたはそれが大体、大きなOだと言うことができるはずです。またはよく、ビッグOは荒れています。 533 00:44:09,410 --> 00:44:15,300 だからあなたは、物事の同じ数をループネストされたforループが表示される場合は、 534 00:44:15,300 --> 00:44:22,260 >> [学生]はn乗 - int型J、J >それが二乗さnする傾向がある。 535 00:44:22,260 --> 00:44:25,280 あなたが三重にネストされている場合、それはn乗になる傾向がある。 536 00:44:25,280 --> 00:44:29,330 だから、そういったことは、あなたはすぐに指摘することができるはずです。 537 00:44:29,330 --> 00:44:33,890 あなたは挿入ソートとバブルソートを知っていて、ソートし、それらのすべてをマージする必要があります。 538 00:44:33,890 --> 00:44:41,420 彼らはそれらのNの2乗とnログnとすべてのことである理由を理解することは簡単だ 539 00:44:41,420 --> 00:44:47,810 私たちは基本的にあなたを与えた1年はクイズであったと思うので、 540 00:44:47,810 --> 00:44:55,050 バブルソートの実装と "この関数の実行時間は何ですか"と言った。 541 00:44:55,050 --> 00:45:01,020 あなたはバブルソートのようにそれを認識するようなら、あなたはすぐにnの二乗と言うことができます。 542 00:45:01,020 --> 00:45:05,470 しかし、あなたはそれを見れば、あなたも、それはバブルソートを実現する必要はありません。 543 00:45:05,470 --> 00:45:08,990 あなただけの、これはこれとこれをやっていると言うことができます。これは乗nです。 544 00:45:12,350 --> 00:45:14,710 [学生]は、あなたが思い付くことができます任意のタフな例がある 545 00:45:14,710 --> 00:45:20,370 考え出すの同様のアイデアが好きですか? 546 00:45:20,370 --> 00:45:24,450 >> 私たちはあなたに何か厳しい例を与えるとは思わない。 547 00:45:24,450 --> 00:45:30,180 バブルソートの事は、私たちが行くだろうと同じくらい厳しいです 548 00:45:30,180 --> 00:45:36,280 さらには限り、あなたは理解するようにして、配列を反復処理していること、という 549 00:45:36,280 --> 00:45:41,670 乗nの何かであることを行っている配列の各要素に対して。 550 00:45:45,370 --> 00:45:49,940 我々が持っているまさにここのような一般的な質問があります - ああ。 551 00:45:55,290 --> 00:45:58,530 先日、ダグは私は配列をソートするアルゴリズムを考案した "と主張 552 00:45:58,530 --> 00:46:01,780 "O(log n)の時間!のn数の" 553 00:46:01,780 --> 00:46:04,900 だから我々は不可能だという方法を知っていますか? 554 00:46:04,900 --> 00:46:08,850 [聞き取れない生徒の応答] >>うん。 555 00:46:08,850 --> 00:46:13,710 少なくとも、あなたは、配列の各要素をタッチする必要があります 556 00:46:13,710 --> 00:46:16,210 ので、それはの配列をソートすることは不可能だ - 557 00:46:16,210 --> 00:46:20,850 すべてがソートされていないためである場合は、アレイ内のすべてのものに触れることになるだろう、 558 00:46:20,850 --> 00:46:25,320 そのためには、nのO未満でそれを行うことは不可能です。 559 00:46:27,430 --> 00:46:30,340 [学生]あなたは私たちにn個のOでそれを行うことができるということの例を示した 560 00:46:30,340 --> 00:46:33,920 あなたは多くのメモリを使用する場合。 >>うん。 561 00:46:33,920 --> 00:46:37,970 とthat's - 私は何that's忘れる - それはソートをカウントされていますか? 562 00:46:47,360 --> 00:46:51,330 うーん。つまり、整数ソートアルゴリズムです。 563 00:46:59,850 --> 00:47:05,100 私は先週、覚えていない可能性があること、このために特別な名前を探していました。 564 00:47:05,100 --> 00:47:13,000 うん。これらは、nの大きなOで物事を達成することができます種類のタイプがあります。 565 00:47:13,000 --> 00:47:18,430 しかし、あなたが特定の番号だけに整数を使用することができますような制限があります。 566 00:47:20,870 --> 00:47:24,560 プラスあなたは何that'sをソートしようとしている場合 - 567 00:47:24,560 --> 00:47:30,750 アレイは012、-12、151、400万であれば、 568 00:47:30,750 --> 00:47:35,120 その後、一つの要素が完全に全体のソートを台無しにしようとしていること。 569 00:47:42,060 --> 00:47:44,030 >> 質問はありますか? 570 00:47:49,480 --> 00:47:58,870 [学生]再帰的な関数を持っている、それだけで再帰呼び出しを行った場合 571 00:47:58,870 --> 00:48:02,230 末尾再帰のreturn文は、内 572 00:48:02,230 --> 00:48:07,360 となるように、実行時に多くのメモリを使用することはありません 573 00:48:07,360 --> 00:48:12,550 反復解法として、または、それは、少なくとも同程度のメモリを使うのでしょうか? 574 00:48:12,550 --> 00:48:14,530 [ボーデン]はい。 575 00:48:14,530 --> 00:48:19,840 それはおそらく本当に多少遅くなることはなくなります。 576 00:48:19,840 --> 00:48:23,290 末尾再帰はかなり良いです。 577 00:48:23,290 --> 00:48:32,640 スタックフレームで再び見ると、みましょう我々はメイン持っていると言う 578 00:48:32,640 --> 00:48:42,920 そして我々はintバー(int型x)、または何かを持っている。 579 00:48:42,920 --> 00:48:52,310 これは完全な再帰関数ではありませんが、リターンバー(X - 1)。 580 00:48:52,310 --> 00:48:57,620 だから明らかに、これは欠陥があります。あなたは、ベースケースとスタッフを必要としています。 581 00:48:57,620 --> 00:49:00,360 しかし、ここでの考え方は、これは末尾再帰であるということです 582 00:49:00,360 --> 00:49:06,020 これは、そのスタックフレームを得るために起こっているときに、メイン通話バーを意味します。 583 00:49:09,550 --> 00:49:12,440 このスタックフレーム内のメモリの小さなブロックがあるように起こっている 584 00:49:12,440 --> 00:49:17,490 それはその引数xに対応しています。 585 00:49:17,490 --> 00:49:25,840 そしてそうしてみましょうすると、メインのバー(100)を呼び出すために起こると言う。 586 00:49:25,840 --> 00:49:30,050 だから、xは100として開始しようとしている。 587 00:49:30,050 --> 00:49:35,660 コンパイラは、これは末尾再帰関数であることを認識した場合、 588 00:49:35,660 --> 00:49:38,540 その後バーはバーへの再帰呼び出しを行ったときに、 589 00:49:38,540 --> 00:49:45,490 代わりに、主に成長しているスタックがどこから始まるかされて新しいスタックフレームを作る、 590 00:49:45,490 --> 00:49:48,220 最終的にはヒープに実行され、その後、セグメンテーションフォルトを取得 591 00:49:48,220 --> 00:49:51,590 メモリは、衝突開始されるため。 592 00:49:51,590 --> 00:49:54,830 >> 代わりに、独自のスタックフレームを作るのはそう、それは、実現することができます 593 00:49:54,830 --> 00:49:59,080 ねえ、私は本当に、このスタックフレームに戻ってくる必要はありません 594 00:49:59,080 --> 00:50:08,040 ので、代わりに私はちょうど99を使用すると、この引数を交換し、バーをすべてやり直すでしょう。 595 00:50:08,040 --> 00:50:11,810 そして、それは再びそれを行うことになり、それがリターンバー(X - 1)に達すると、 596 00:50:11,810 --> 00:50:17,320 その代わりに新しいスタックフレームを作るのは、それだけで98と現在の引数に置き換えられます 597 00:50:17,320 --> 00:50:20,740 その後バーの冒頭にジャンプして戻る。 598 00:50:23,860 --> 00:50:30,430 これらの操作は、スタック上でその1つの値を交換すると最初に戻ってジャンプし、 599 00:50:30,430 --> 00:50:32,430 かなり効率的です。 600 00:50:32,430 --> 00:50:41,500 だからだけではなく、これは反復される別個の関数と同じようにメモリ使用量です 601 00:50:41,500 --> 00:50:45,390 あなただけの1スタックフレームを使用していますが、マイナス面を被っていないため 602 00:50:45,390 --> 00:50:47,240 関数を呼び出すする必要がなくなります。 603 00:50:47,240 --> 00:50:50,240 それはすべてこの設定を行う必要があるため、関数の呼び出しは、多少高価になることができます 604 00:50:50,240 --> 00:50:52,470 とティアダウンおよびすべてのこのようなもの。 605 00:50:52,470 --> 00:50:58,160 だから、これは末尾再帰は良いです。 606 00:50:58,160 --> 00:51:01,170 [学生]なぜそれは、新しいステップを作成しないのですか? 607 00:51:01,170 --> 00:51:02,980 それが実現しているので、その必要はありません。 608 00:51:02,980 --> 00:51:07,800 バーへの呼び出しは単に再帰呼び出しを返しています。 609 00:51:07,800 --> 00:51:12,220 だから、戻り値を使って何かする必要はありません。 610 00:51:12,220 --> 00:51:15,120 それだけで、すぐにそれを返すことになるだろう。 611 00:51:15,120 --> 00:51:20,530 だから、それだけで、独自の引数を交換して、最初からやり直しになるだろう。 612 00:51:20,530 --> 00:51:25,780 そしてまた、あなたは末尾再帰バージョンをお持ちでない場合は、 613 00:51:25,780 --> 00:51:31,460 その後、このバーが返すすべてのこれらのバーを取得 614 00:51:31,460 --> 00:51:36,010 それはバーがすぐに戻りますが、次に、このいずれかにその値を返す必要があります 615 00:51:36,010 --> 00:51:39,620 そしてそれはこの1つにその値を返し、それだけですぐに戻るようになるだろう 616 00:51:39,620 --> 00:51:41,350 そしてこのいずれかにその値を返します。 617 00:51:41,350 --> 00:51:45,350 だからあなたは、スタックのこれらの事のすべてを飛び出し、これを保存している 618 00:51:45,350 --> 00:51:48,730 戻り値は、とにかく戻ってすべての道を渡されようとしているからです。 619 00:51:48,730 --> 00:51:55,400 それでは、どうしてアップデート引数と共に私たちの引数を交換して、最初からやり直しませんか? 620 00:51:57,460 --> 00:52:01,150 あなたのような何かをする場合、この関数は、末尾再帰ではない場合 - 621 00:52:01,150 --> 00:52:07,530 バーなら[学生](x + 1)を。 >>うん。 622 00:52:07,530 --> 00:52:11,770 >> あなたは条件に入れてもしそうなら、あなたは、戻り値を使って何かをやっている。 623 00:52:11,770 --> 00:52:16,260 それとも、ただリターン2を行う場合でも、*バー(X - 1)。 624 00:52:16,260 --> 00:52:23,560 だから今バー(X - 1)は2回、その値を計算するために返す必要があり、 625 00:52:23,560 --> 00:52:26,140 ので、今それはそれ自身の独立したスタックフレームを必要としている、 626 00:52:26,140 --> 00:52:31,180 そして今、あなたは一生懸命やっていても、あなたはする必要があるとしていないしている - 627 00:52:31,180 --> 00:52:34,410 これは末尾再帰ではありません。 628 00:52:34,410 --> 00:52:37,590 [学生]私は末尾再帰を目指して再帰を持ってみませんか - 629 00:52:37,590 --> 00:52:41,450 [ボーデン]理想の世界では、しかし、CS50にあなたがする必要はありません。 630 00:52:43,780 --> 00:52:49,280 末尾再帰を取得するためには、一般的には、追加の引数を設定 631 00:52:49,280 --> 00:52:53,550 バーは、yにint型のxを取る場所 632 00:52:53,550 --> 00:52:56,990 とyは戻したい究極のものに対応しています。 633 00:52:56,990 --> 00:53:03,650 ( - ×1)、2 * Yだから、これはあなたがバーを返すことになるだろう。 634 00:53:03,650 --> 00:53:09,810 だから、それは、あなたが物事を末尾再帰にする変換方法だけハイレベルだ。 635 00:53:09,810 --> 00:53:13,790 しかし、余分な引数 - 636 00:53:13,790 --> 00:53:17,410 そして、最後に、あなたのベースケースに達したときに、あなただけyを返す 637 00:53:17,410 --> 00:53:22,740 あなたが望むことを、全体の時間の戻り値を蓄積してきたので。 638 00:53:22,740 --> 00:53:27,280 に、どのような種類の繰り返しそれをやってますが、再帰呼び出しを使用してきました。 639 00:53:32,510 --> 00:53:34,900 質問はありますか? 640 00:53:34,900 --> 00:53:39,890 文字列を使用する場合のようにたぶん、ポインタ演算について[学生]。 >>確かに。 641 00:53:39,890 --> 00:53:43,610 ポインタ演算。 642 00:53:43,610 --> 00:53:48,440 文字列はchar型星であるので、文字列を使用する場合、それは簡単です、 643 00:53:48,440 --> 00:53:51,860 charsは、永遠に、常に単一バイトで 644 00:53:51,860 --> 00:53:57,540 あなたは文字列を扱う場合など、ポインタ演算は、通常の算術演算に相当します。 645 00:53:57,540 --> 00:54:08,790 ただのchar * S = "こんにちは"と言ってみましょう。 646 00:54:08,790 --> 00:54:11,430 だから我々はメモリ内のブロックを持っています。 647 00:54:19,490 --> 00:54:22,380 あなたは常にnullターミネータを必要とするので、それは6バイトを必要とします。 648 00:54:22,380 --> 00:54:28,620 とchar * sは、この配列の先頭を指すようになるだろう。 649 00:54:28,620 --> 00:54:32,830 そこのポイントはそう。 650 00:54:32,830 --> 00:54:36,710 さて、これは、基本的に任意の配列がどのように動作するかです 651 00:54:36,710 --> 00:54:40,780 かかわらず、それはmalloc関数により、またはそれがスタック上にあるかどうか復帰したかどうかの。 652 00:54:40,780 --> 00:54:47,110 任意の配列は、基本的には配列の先頭へのポインタである 653 00:54:47,110 --> 00:54:53,640 し、任意の配列操作、任意のインデックス付けは、単に特定のオフセット、その配列に起こっている。 654 00:54:53,640 --> 00:55:05,360 >> だから私は、s [3]のような何かを言うとき、これはsに行くとインチ3文字をカウントしている 655 00:55:05,360 --> 00:55:12,490 だからsが[3]、[3]は、0、1、2、3、ので、sを持っているこのリットルを参照しようとしている。 656 00:55:12,490 --> 00:55:20,460 [学生]そして我々はS + 3をやって、その後に括弧スターが同じ値に達する可能性がある? 657 00:55:20,460 --> 00:55:22,570 はい。 658 00:55:22,570 --> 00:55:26,010 これは*(S + 3)と同等です。 659 00:55:26,010 --> 00:55:31,240 そしてそれは永遠に、常に同等のあなたが何をするかに関係なくはありません。 660 00:55:31,240 --> 00:55:34,070 あなたは、括弧構文を使用する必要はありません。 661 00:55:34,070 --> 00:55:37,770 あなたは、常に*(S + 3)構文を使用することができます。 662 00:55:37,770 --> 00:55:40,180 人々は、しかし、ブラケット構文を好む傾向にある。 663 00:55:40,180 --> 00:55:43,860 [学生]だから、すべての配列は実際には単なるポインタである。 664 00:55:43,860 --> 00:55:53,630 私はと言うと少しだけ違いがあります。int x [4]; >> [学生]はメモリを作成していますか? 665 00:55:53,630 --> 00:56:03,320 [ボーデン]ので、16バイト全体的に、スタック上の4個のint値を作成しようとしていること。 666 00:56:03,320 --> 00:56:05,700 これは、スタック上に16バイトを作成するために起こっている。 667 00:56:05,700 --> 00:56:09,190 xはどこにも格納されません。 668 00:56:09,190 --> 00:56:13,420 それだけの事の開始を参照シンボルです。 669 00:56:13,420 --> 00:56:17,680 あなたは、この関数の内部で配列を宣言しているので、 670 00:56:17,680 --> 00:56:22,340 コンパイラは何をするつもりなのか単なる変数xのすべてのインスタンスを置換される 671 00:56:22,340 --> 00:56:26,400 それはこれらの16バイトを置くことを選択することが起こった場所である。 672 00:56:26,400 --> 00:56:30,040 sは実際のポインタなので、これはchar * sであることを行うことはできません。 673 00:56:30,040 --> 00:56:32,380 そして、それは他のことを指すように自由である。 674 00:56:32,380 --> 00:56:36,140 xは定数である。は、別の配列にポイントを持つことができません。 >> [生徒]オーケー。 675 00:56:36,140 --> 00:56:43,420 しかし、このアイデア、このインデックスは、それが伝統的な配列であるかどうかにかかわらず同じです。 676 00:56:43,420 --> 00:56:48,230 またはそれは何かへのポインタであるかのまたはそれはmallocされた配列へのポインタましょう。 677 00:56:48,230 --> 00:56:59,770 そして、実際に、それはまた同じ事であるように等価である。 678 00:56:59,770 --> 00:57:05,440 これは、実際には、ブラケットとブラケットのどんな残っているの内側にあるものだけ変換 679 00:57:05,440 --> 00:57:07,970 それらを一緒に追加して、間接参照。 680 00:57:07,970 --> 00:57:14,710 だから、これは*(S + 3)またはs [3]と同じように有効です。 681 00:57:16,210 --> 00:57:22,090 [学生]あなたは2次元配列を指すポインタを持つことはできますか? 682 00:57:22,090 --> 00:57:27,380 >> それが難しくなっています。伝統的に、ない。 683 00:57:27,380 --> 00:57:34,720 2次元配列は、単にいくつかの便利な構文を持つ1次元配列である 684 00:57:34,720 --> 00:57:54,110 なぜなら私が言うときます。int x [3] [3]、これは実際に9個の値を持つだけで1アレイです。 685 00:57:55,500 --> 00:58:03,000 そして私インデックスは、コンパイラは、私が何を意味するか知っているとき。 686 00:58:03,000 --> 00:58:13,090 私はx [1] [2]、それは私は2番目の行に移動したい知っているので、それは最初の3をスキップして起こっていると言うなら 687 00:58:13,090 --> 00:58:17,460 そしてそれはその中で第二の事を望んでいるので、それはこの1つを得るために起こっている。 688 00:58:17,460 --> 00:58:20,480 しかし、それはまだほんの一次元配列です。 689 00:58:20,480 --> 00:58:23,660 そして私は、その配列へのポインタを代入したい場合 690 00:58:23,660 --> 00:58:29,770 私は言うだろます。int * p = X; 691 00:58:29,770 --> 00:58:33,220 xの型はただです - 692 00:58:33,220 --> 00:58:38,280 それだけではシンボルであり、それは実際の変数ではないので、それは、xの荒いタイプだと言って 693 00:58:38,280 --> 00:58:40,140 それだけでint *になります。 694 00:58:40,140 --> 00:58:44,840 xがちょうどこのの先頭へのポインタです。 >> [生徒]オーケー。 695 00:58:44,840 --> 00:58:52,560 そして、私は[1] [2]にアクセスすることができません。 696 00:58:52,560 --> 00:58:58,370 私は、ポインタを宣言するための特別な構文があると思います 697 00:58:58,370 --> 00:59:12,480 int型のようなとんでもない何かが(* P [ - 。絶対にばかげ何か私も知りません。 698 00:59:12,480 --> 00:59:17,090 しかし、括弧や物事とのようなポインタを宣言するための構文があります。 699 00:59:17,090 --> 00:59:22,960 それも、あなたはそれを行うことができない場合があります。 700 00:59:22,960 --> 00:59:26,640 私は私に本当のことを言うだろう何かを振り返ることができます。 701 00:59:26,640 --> 00:59:34,160 ポイントの構文がある場合、私は後でそれを探します。しかし、あなたはそれを参照することはありません。 702 00:59:34,160 --> 00:59:39,670 とさえ構文は、あなたがそれを使用する場合、人々は困惑されるように古風です。 703 00:59:39,670 --> 00:59:43,540 そのままでは多次元配列はかなり稀だ。 704 00:59:43,540 --> 00:59:44,630 かなりあなた - 705 00:59:44,630 --> 00:59:48,490 さて、あなたは行列のことをやっている場合、それはまれであることを行っていない、 706 00:59:48,490 --> 00:59:56,730 しかし、C言語では滅多に多次元配列を使用するつもりんだ。 707 00:59:57,630 --> 01:00:00,470 うん。 >> [生徒] Let 'sは、あなたが本当に長い配列を持っていると言う。 708 01:00:00,470 --> 01:00:03,900 >> だから、仮想メモリには、すべての連続であるように見えるでしょう 709 01:00:03,900 --> 01:00:05,640 互いに右隣の要素のように、 710 01:00:05,640 --> 01:00:08,770 しかし、物理メモリには、分割することは可能でしょうか? >>はい。 711 01:00:08,770 --> 01:00:16,860 それだけで分離する方法、仮想メモリの作品です - 712 01:00:19,220 --> 01:00:24,860 割り当ての単位は、4キロバイトになる傾向があるページです 713 01:00:24,860 --> 01:00:29,680 と、プロセスはちょっと、と言うとき、私はこのメモリを使用したいが、 714 01:00:29,680 --> 01:00:35,970 オペレーティングシステムはそれをメモリの小さなブロックのための4キロバイトを割り当てるために起こっている。 715 01:00:35,970 --> 01:00:39,100 あなただけのメモリのブロック全体で単一の小さなバイトを使用している場合でも、 716 01:00:39,100 --> 01:00:42,850 オペレーティング·システムはそれをフル4キロバイトを与えるために起こっている。 717 01:00:42,850 --> 01:00:49,410 だから意味が何であるか、私は可能性があります - これは私のスタックであると言いましょう。 718 01:00:49,410 --> 01:00:53,180 このスタックは、分離することができた。私のスタックはメガバイトとメガバイトである可能性があります。 719 01:00:53,180 --> 01:00:55,020 私のスタックが非常に大きくなることがあります。 720 01:00:55,020 --> 01:01:00,220 しかし、スタック自体は、個々のページに分割する必要があります 721 01:01:00,220 --> 01:01:09,010 これが私たちのRAMであると言う私達はこっちを見ればどの聞かせ、 722 01:01:09,010 --> 01:01:16,600 私は2 GBのRAMを持っている場合、これは、私のRAMのゼロ番目のバイトのように実際のアドレス0である 723 01:01:16,600 --> 01:01:22,210 そして、これはここにすべての方法2ギガバイトダウンしています。 724 01:01:22,210 --> 01:01:27,230 だからこのページはこっちこのブロックに対応している場合があります。 725 01:01:27,230 --> 01:01:29,400 このページにはこっちこのブロックに対応している場合があります。 726 01:01:29,400 --> 01:01:31,560 この1つはこっちにこのいずれかに対応している場合があります。 727 01:01:31,560 --> 01:01:35,540 オペレーティングシステムは、物理メモリを割り当てることが自由であるように 728 01:01:35,540 --> 01:01:39,320 任意の個々のページに移動します。 729 01:01:39,320 --> 01:01:46,180 そして、それはつまり、この境界線はアレイを跨ぐように起これば、 730 01:01:46,180 --> 01:01:50,070 配列は、この左側れるようなことが起こると右のページのこの注文の 731 01:01:50,070 --> 01:01:54,460 その配列は、物理メモリに分割されようとしている。 732 01:01:54,460 --> 01:01:59,280 プロセスが終了すると、その後は、プログラムを終了するとき、 733 01:01:59,280 --> 01:02:05,690 これらのマッピングは消去取得し、それは他のもののために、これらの小さなブロックを自由に使用することです。 734 01:02:14,730 --> 01:02:17,410 多くの質問? 735 01:02:17,410 --> 01:02:19,960 [学生]ポインタ演算。 >>そうそう。 736 01:02:19,960 --> 01:02:28,410 文字列は、簡単であったが、int型のようなものを見て 737 01:02:28,410 --> 01:02:35,000 そう背中にint X [4]; 738 01:02:35,000 --> 01:02:41,810 これが配列されているかどうか、それが4つの整数のmallocされた配列へのポインタであるかどうか、 739 01:02:41,810 --> 01:02:47,060 それは同じように扱われるようになるだろう。 740 01:02:50,590 --> 01:02:53,340 [学生]だから配列はヒープ上にある? 741 01:03:01,400 --> 01:03:05,270 [ボーデン]配列はヒープ上にありません。 >> [生徒]ああ。 742 01:03:05,270 --> 01:03:08,320 >> [ボーデン]配列のこのタイプは、スタック上になる傾向がある 743 01:03:08,320 --> 01:03:12,220 あなたがそれをで宣言しない限り - グローバル変数を無視します。グローバル変数を使用しないでください。 744 01:03:12,220 --> 01:03:16,280 関数の内部で私が言います。int x [4]; 745 01:03:16,280 --> 01:03:22,520 それは、この配列のスタッ​​ク上の4整数ブロックを作成するために起こっている。 746 01:03:22,520 --> 01:03:26,960 しかし、これはmalloc(4 * sizeofは(int型));ヒープ上に行くつもりです。 747 01:03:26,960 --> 01:03:31,870 しかし、このポイントの後、私は、ほとんど同じ方法で、xとpを使用することができます 748 01:03:31,870 --> 01:03:36,140 あなたが電話を再割り当てすることができ、約前に私が言った例外以外。 749 01:03:36,140 --> 01:03:40,960 技術的には、そのサイズは多少異なりますが、それは完全に無関係です。 750 01:03:40,960 --> 01:03:43,310 あなたは実際にそのサイズを使用することはありません。 751 01:03:48,020 --> 01:03:56,810 私が言うことができるP P [3] = 2;またはx [3] = 2; 752 01:03:56,810 --> 01:03:59,680 あなたは正確に同じ方法でそれらを使用することができます。 753 01:03:59,680 --> 01:04:01,570 ここで行ってポインタ演算 - はい。 754 01:04:01,570 --> 01:04:07,390 [学生]あなたは括弧を使用している場合p *を行う必要はありませんか? 755 01:04:07,390 --> 01:04:11,720 ブラケットは暗黙間接参照されています。オーケー。>> 756 01:04:11,720 --> 01:04:20,200 実際にも、あなたが言っているあなたは、多次元配列を得ることができます 757 01:04:20,200 --> 01:05:02,650 ポインタで、何を行うことができますこととしましょう​​、何かに似ていますが、int **にPP =はmalloc(sizeofの(int型*)* 5); 758 01:05:02,650 --> 01:05:06,900 私は最初それを全て書いていきます。 759 01:05:37,880 --> 01:05:41,020 私はそのいずれかをしたくなかった。 760 01:05:41,020 --> 01:05:42,550 オーケー。 761 01:05:42,550 --> 01:05:48,910 私がここで何をしたかは - PP [i]がされるべきであること。 762 01:05:48,910 --> 01:05:53,680 だからppはポインタへのポインタです。 763 01:05:53,680 --> 01:06:02,420 あなたは5つのintの配列へのポインタppのmallocingいる。 764 01:06:02,420 --> 01:06:10,950 だから、メモリには、スタックの頁にあり 765 01:06:10,950 --> 01:06:20,150 それは、すべてのポインタそのものである5ブロックの配列を指すようになるだろう。 766 01:06:20,150 --> 01:06:28,210 そして、ときに、ここで私は、mallocダウン、私はmallocそのそれらの個々のポインタの各 767 01:06:28,210 --> 01:06:32,080 ヒープ上に4バイトの別のブロックを指す必要があります。 768 01:06:32,080 --> 01:06:35,870 4バイトを指してこれがそう。 769 01:06:37,940 --> 01:06:40,660 と別の4バイトには、この1点。 770 01:06:40,660 --> 01:06:43,200 >> それらのすべては、自分の4バイトを指す。 771 01:06:43,200 --> 01:06:49,080 これは私に多次元物事のやり方を提供します。 772 01:06:49,080 --> 01:06:58,030 私は、ppは[3] [4]が、今、これは多次元配列とは、同じではないと言うことができる 773 01:06:58,030 --> 01:07:05,390 多次元配列は、それが[3]翻訳しているため[4] x配列へのオフセットシングルに。 774 01:07:05,390 --> 01:07:14,790 この間接参照pは、デその次に、第三索引にアクセス 775 01:07:14,790 --> 01:07:20,790 とアクセス - 4は無効になる - 番目のインデックス。 776 01:07:24,770 --> 01:07:31,430 一方、我々が持っていたときます。int x [3] [4]多次元配列として前 777 01:07:31,430 --> 01:07:35,740 とブラケットをダブルクリックすると、それは、本当に唯一の単一の間接参照です 778 01:07:35,740 --> 01:07:40,490 あなたは、単一のポインタとオフセットをフォローしている、 779 01:07:40,490 --> 01:07:42,850 これは本当に2D参照です。 780 01:07:42,850 --> 01:07:45,840 あなたは、2つの独立したポインタに従ってください。 781 01:07:45,840 --> 01:07:50,420 だから、これも技術的には多次元配列を持つことができます 782 01:07:50,420 --> 01:07:53,550 個々の配列は、異なるサイズです。 783 01:07:53,550 --> 01:07:58,000 だから私はギザギザの多次元配列は、それが呼ばれるものだと思う 784 01:07:58,000 --> 01:08:01,870 本当に以来、最初のものは、10個の要素を持つものを指すことが 785 01:08:01,870 --> 01:08:05,540 二つ目は、100個の要素を持っている何かを示すかもしれません。 786 01:08:05,540 --> 01:08:10,790 [学生]あなたが持つことができるポインタの数に制限はありますか 787 01:08:10,790 --> 01:08:14,290 他のポインタを指している?ナンバー>> 788 01:08:14,290 --> 01:08:17,010 あなたはint ***** pを持つことができます。 789 01:08:18,050 --> 01:08:23,760 戻るポインタ演算 - >> [生徒]ああ。 >>うん。 790 01:08:23,760 --> 01:08:35,649 [学生]私はその後のint *** pを持っている場合、私は参照外しを行うと、私はP *がこの値と等しいと言う、 791 01:08:35,649 --> 01:08:39,560 それが唯一の間接参照のレベル1をやろうとすると? >>はい。 792 01:08:39,560 --> 01:08:43,340 だから私は、最後のポインタが指しているものにアクセスしたい場合は - 793 01:08:43,340 --> 01:08:46,210 その後、*** pを行う。オーケー。>> 794 01:08:46,210 --> 01:08:54,080 だから、これは1ブロックにp点、別のブロックを指し、別のブロックを指しています。 795 01:08:54,080 --> 01:09:02,010 あなたは* P =何かを行う場合、あなたはこれを変更している 796 01:09:02,010 --> 01:09:13,640 現在は別のブロックを指すように設定します。オーケー。>> 797 01:09:13,640 --> 01:09:17,649 >> これらはmallocされた場合[ボーデンは]そして、あなたはすぐにメモリをリークしていた 798 01:09:17,649 --> 01:09:20,430 あなたは、これらの異なる基準を持って起こる場合を除き 799 01:09:20,430 --> 01:09:25,270 あなたはただ捨てたことをこれらのものに戻って取得することができないので。 800 01:09:25,270 --> 01:09:29,550 ポインタ演算。 801 01:09:29,550 --> 01:09:36,310 ます。int x [4]; 4つの整数の配列を割り当てるために起こっている 802 01:09:36,310 --> 01:09:40,670 ここで、xは、配列の先頭を指すようになるだろう。 803 01:09:40,670 --> 01:09:50,420 だから私は、x [1]のような何かを言うとき、私はそれが配列の2番目の整数に行くことを意味する、 804 01:09:50,420 --> 01:09:53,319 これは、この1となります。 805 01:09:53,319 --> 01:10:04,190 この整数は4バイトを占有しますので、しかし、実際に、その配列に4バイトです。 806 01:10:04,190 --> 01:10:08,470 1のオフセットは本当に1のオフセットを意味しますので、 807 01:10:08,470 --> 01:10:12,030 回配列の型が何であれのサイズ。 808 01:10:12,030 --> 01:10:17,170 これは、整数の配列であるため、それがオフセットしたい場合、int型の1倍のサイズを行うことを知っています。 809 01:10:17,170 --> 01:10:25,260 他の構文。これは*(X + 1)と等価であることを忘れないでください; 810 01:10:25,260 --> 01:10:35,250 私はポインタ+ 1は、リターンはポインタが格納されているアドレスであることを言うときは 811 01:10:35,250 --> 01:10:40,360 ポインタの型のプラス1倍の大きさ。 812 01:10:40,360 --> 01:10:59,510 だから、もしx = OX100の場合、x + 1 = ox104。 813 01:10:59,510 --> 01:11:19,750 そして、あなたはこれを濫用し、charのようなものを言うことができます* C =(char *)のX; 814 01:11:19,750 --> 01:11:23,050 そして今Cは、Xと同じアドレスになるだろう。 815 01:11:23,050 --> 01:11:26,040 cは、OX100に等しいことになるだろう 816 01:11:26,040 --> 01:11:31,490 が、c + 1 ox101に等しいことになるだろう 817 01:11:31,490 --> 01:11:38,030 ポインタ演算は、あなたが追加しているポインタの型に依存しているため。 818 01:11:38,030 --> 01:11:45,390 だからC + 1、それはCを見て、それはchar型のポインタなので、それはcharの1倍の大きさを追加するために起こっている 819 01:11:45,390 --> 01:11:48,110 これは、常に1であることを行っているので、101を取得し、 820 01:11:48,110 --> 01:11:54,890 私はまだ100もあるxを行う場合は、x + 1が104であることを行っているのに対し。 821 01:11:56,660 --> 01:12:06,340 [学生]は、C + + 1であなたのポインタを前進させるために使用することはできますか? 822 01:12:06,340 --> 01:12:09,810 はい、できます。 823 01:12:09,810 --> 01:12:16,180 あなたは、xを変更することはできませんので、xがただの記号なので、xと、それが一定であることを行うことはできません。 824 01:12:16,180 --> 01:12:22,610 >> しかし、cは単なるポインタであることを起こるので、C + +は完全に有効であり、それが1ずつ増加します。 825 01:12:22,610 --> 01:12:32,440 cは単にint *にあった場合、C + + 104されるであろう。 826 01:12:32,440 --> 01:12:41,250 + +は、C + 1は、ポインタ演算を行っているのと同じようにポインタ演算を行います。 827 01:12:43,000 --> 01:12:48,870 これは実際にはマージソートのようなたくさんの方法です - 828 01:12:49,670 --> 01:12:55,710 代わりに物事のコピーを作成するのではなく、代わりに渡すことができます - 829 01:12:55,710 --> 01:13:02,400 この一部を消去してみましょう - 私はこの配列の半分を渡したい場合は、好きです。 830 01:13:04,770 --> 01:13:10,520 Let 'sは、私は、関数に配列のこちら側を通過したいとしましょう​​。 831 01:13:10,520 --> 01:13:12,700 私は、その関数に渡すでしょうか? 832 01:13:12,700 --> 01:13:17,050 私はxを渡した場合、私は、このアドレスを渡しています。 833 01:13:17,050 --> 01:13:23,780 しかし、私はこの特定のアドレスを渡したい。だから私は何を渡すべきでしょうか? 834 01:13:23,780 --> 01:13:26,590 [学生]ポインタ+ 2? 835 01:13:26,590 --> 01:13:29,350 [ボーデン]だからX + 2。はい。 836 01:13:29,350 --> 01:13:31,620 それは、このアドレスになるだろう。 837 01:13:31,620 --> 01:13:42,810 また、非常に頻繁に、それはそれの後、アドレスx [2]のように表示されます。 838 01:13:42,810 --> 01:13:47,850 だから、ブラケットが暗黙の逆参照であるため、それのアドレスを取得する必要があります。 839 01:13:47,850 --> 01:13:53,250 X [2]、このボックスに表示されている値を参照し、次にそのボックスのアドレスを取得したく 840 01:13:53,250 --> 01:13:56,850 そうあなたが言うとX [2]。 841 01:13:56,850 --> 01:14:02,880 だからそれはあなたが何かに半分のリストを渡したいマージソートでどのように何か 842 01:14:02,880 --> 01:14:08,790 あなたが本当にちょうど渡す&X [2]、現在は限り再帰呼び出しが懸念している、 843 01:14:08,790 --> 01:14:12,510 私の新しい配列がそこから始まります。 844 01:14:12,510 --> 01:14:15,130 直前の質問。 845 01:14:15,130 --> 01:14:20,050 [学生]私たちは、アンパサンドを置いたりしない場合 - それは何という名前ですか? >>スター? 846 01:14:20,050 --> 01:14:23,200 [学生]スター。 >>技術的には、間接参照演算子が、 - >> [生徒]参照外しをしています。 847 01:14:23,200 --> 01:14:29,310 >> 我々は、私はちょうど言う場合は、y = xとxのポインタですか何が起こるか、スターまたはアンパサンドを入れない場合 848 01:14:29,310 --> 01:14:34,620 yの型は何ですか? >> [学生]私はちょうどそれのポインタ2を言うでしょう。 849 01:14:34,620 --> 01:14:38,270 あなただけ言うのであればy = xを、現在のxとyの点と同じことに。 >>同じ事を[学生]をポイントします。 850 01:14:38,270 --> 01:14:45,180 、xはint型のポインタである場合はどうなりますか?あなたはポインタを代入することはできませんので、>>それは文句を言うだろう。 851 01:14:45,180 --> 01:14:46,540 [学生]オーケー。 852 01:14:46,540 --> 01:14:51,860 我々は矢のようにそれらを描くにもかかわらず、そのポインタを覚えて、 853 01:14:51,860 --> 01:15:02,010 本当に彼らはすべての店 - int型* xは - 本当にすべてのxが保存されているが、OX100のようなものです 854 01:15:02,010 --> 01:15:06,490 その我々は100に格納されているブロックを指すように表現するために起こる。 855 01:15:06,490 --> 01:15:19,660 だから私が言うとき、int *にy = xと、私はちょうどyにOX100をコピーするんだけど、 856 01:15:19,660 --> 01:15:24,630 その我々だけでもOX100を指すようにすれば、yと表すことになるだろう。 857 01:15:24,630 --> 01:15:39,810 そして私はと言えばます。int i =(int)をX;それから私はOX100の値が何であっても保存しようとしている 858 01:15:39,810 --> 01:15:45,100 その内側が、現在ではなく、整数型のポインタとして解釈されることになるだろう。 859 01:15:45,100 --> 01:15:49,310 しかし、あなたはキャストを必要とするか、またはそうでなければ文句を言うでしょう。 860 01:15:49,310 --> 01:15:53,300 [学生]だからあなたはキャストすることを意味しな​​い - 861 01:15:53,300 --> 01:16:00,290 それは、yのxまたはキャストintのintをキャストしようとしている? 862 01:16:00,290 --> 01:16:03,700 [ボーデン]何? 863 01:16:03,700 --> 01:16:07,690 [学生]オーケー。これらの括弧の後にそこには、xまたはAYそこになるだろうか? 864 01:16:07,690 --> 01:16:11,500 >> [ボーデン]のどちらか。 xとyは等価です。 >> [生徒]オーケー。 865 01:16:11,500 --> 01:16:14,390 彼らは両方のポインタだから。 >>うん。 866 01:16:14,390 --> 01:16:21,050 [学生]だからそれは整数の形で進数100を格納するでしょうか? >> [ボーデン]うん。 867 01:16:21,050 --> 01:16:23,620 それが指すものは何でもではなく値。 868 01:16:23,620 --> 01:16:29,940 [ボーデン]うん。 >> [生徒]だから整数形式でアドレスだけ。オーケー。 869 01:16:29,940 --> 01:16:34,720 あなたには、いくつかの奇妙な理由のために、必要であれば[ボーデン] 870 01:16:34,720 --> 01:16:38,900 あなたは、排他的にポインタを扱うと整数を扱うことができませんでした 871 01:16:38,900 --> 01:16:49,240 そしてちょうどint型* x = 0のようになる。 872 01:16:49,240 --> 01:16:53,000 次に、ポインタ演算が起き始めると本当に混乱するつもりだ。 873 01:16:53,000 --> 01:16:56,570 そこで、彼らは保存しておくことを数字は意味がありません。 874 01:16:56,570 --> 01:16:58,940 それはあなたがそれらを解釈してしまうだけの方法です。 875 01:16:58,940 --> 01:17:02,920 だから私は、int型にint *からOX100をコピーすることが自由だ 876 01:17:02,920 --> 01:17:07,790 おそらくキャストしないために怒鳴ら取得するつもりyou're - と私は割り当てることは自由だ - 877 01:17:07,790 --> 01:17:18,160 私は、この任意のint *に(i​​nt *)をox1234ような何かを割り当てることが自由だ。 878 01:17:18,160 --> 01:17:25,480 &yであるようにox123は同じように有効なメモリアドレスです。 879 01:17:25,480 --> 01:17:32,060 &Yはかなりox123ものを返すことが起こる。 880 01:17:32,060 --> 01:17:35,430 [学生]は、16進数から10進形式に行くために本当にクールな方法であろう、 881 01:17:35,430 --> 01:17:39,230 あなたはポインタを持っていて、int型にキャストした場合好きですか? 882 01:17:39,230 --> 01:17:44,860 [ボーデン]あなたは本当にprintfのように使用して印刷することができます。 883 01:17:44,860 --> 01:17:50,300 Let 'sは、私はint型のy = 100を持っていると言う。 884 01:17:50,300 --> 01:18:02,700 だからprintfの(%d個\ nを - あなたが知っておくべきこととして - %xは、整数としてそれを印刷してください。 885 01:18:02,700 --> 01:18:05,190 我々は、ちょうど16進数として、それを印刷します。 886 01:18:05,190 --> 01:18:10,760 だからポインタは、16進数として格納されていません 887 01:18:10,760 --> 01:18:12,960 と整数は小数として格納されていません。 888 01:18:12,960 --> 01:18:14,700 すべてはバイナリとして格納されます。 889 01:18:14,700 --> 01:18:17,950 それは、我々は16進数としてポインタを示す傾向にあるというだけです 890 01:18:17,950 --> 01:18:23,260 私たちは、これらの4バイトのブロック単位で物事を考えるので、 891 01:18:23,260 --> 01:18:25,390 とメモリアドレスは精通している傾向があります。 892 01:18:25,390 --> 01:18:28,890 それはBFで始まる場合、それはスタック上にあることを起こる、のように私たちはいる。 893 01:18:28,890 --> 01:18:35,560 だから、それだけで16進数としてポインタの我々の解釈だ。 894 01:18:35,560 --> 01:18:39,200 オーケー。任意の最後の質問? 895 01:18:39,200 --> 01:18:41,700 >> あなたが何かを持っているかの後、私は少しのためにここにいるよ。 896 01:18:41,700 --> 01:18:46,070 そして、それはそれの終わりです。 897 01:18:46,070 --> 01:18:48,360 >> [学生]イェーイ! [拍手] 898 01:18:51,440 --> 01:18:53,000 >> [CS50.TV]