1 00:00:00,000 --> 00:00:02,520 [Powered by Google Translate] [Часть 4 - более комфортной] 2 00:00:02,520 --> 00:00:04,850 [Rob Боуден - Гарвардский университет] 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 но обычно вы не волнуйтесь об этом, и вы просто говорите х + 2, у + 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 >> Я хочу объявить указатель р. Что же типа выглядят? 22 00:01:26,210 --> 00:01:33,530 [Студент] Int * р. >> Да. Так Int * р. 23 00:01:33,530 --> 00:01:38,030 А как сделать, чтобы она указывала на х? >> [Студент] Ampersand. 24 00:01:40,540 --> 00:01:45,300 [Боуден] Так амперсанд буквально называется адрес оператора. 25 00:01:45,300 --> 00:01:50,460 Поэтому, когда я говорю, и х он становится адрес памяти переменной х. 26 00:01:50,460 --> 00:01:56,790 Так что теперь у меня есть указатель р, и в любом месте в моем коде я могу использовать * р 27 00:01:56,790 --> 00:02:02,960 или я мог бы использовать х, и это будет одно и то же. 28 00:02:02,960 --> 00:02:09,520 (* Р). Что это делаешь? Что означает, что звезда в виду? 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, 32 00:02:22,230 --> 00:02:25,980 Затем у нас есть маленькая коробочка памяти для р, 33 00:02:25,980 --> 00:02:31,590 и так с точки х, так что мы рисуем стрелку от р х. 34 00:02:31,590 --> 00:02:40,270 Поэтому когда мы говорим * р мы говорим пойти в окно, р. 35 00:02:40,270 --> 00:02:46,480 Звезда следуйте за стрелкой, а затем делать все, что вы хотите с этой коробке прямо там. 36 00:02:46,480 --> 00:03:01,090 Поэтому я могу сказать * р = 7, и что пойдет на ящик, который является х и изменения, которые до 7. 37 00:03:01,090 --> 00:03:13,540 Или я мог бы сказать Int г = * р * 2; Это заблуждение, потому что это звезда, звезда. 38 00:03:13,540 --> 00:03:19,230 Одна звезда разыменования р, другая звезда умножением на 2. 39 00:03:19,230 --> 00:03:26,780 Обратите внимание, я мог бы с таким же успехом заменили * р с х. 40 00:03:26,780 --> 00:03:29,430 Вы можете использовать их таким же образом. 41 00:03:29,430 --> 00:03:38,000 А потом на меня может быть с точки на совершенно новую вещь. 42 00:03:38,000 --> 00:03:42,190 Я могу только сказать, р = &z; 43 00:03:42,190 --> 00:03:44,940 Так что теперь P больше не указывает на х; он указывает на г. 44 00:03:44,940 --> 00:03:50,510 И в любое время я * р это так же, как делал г. 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 Но когда вы получаете в функции - так скажем, у нас есть некоторые функции, внутр Фу, 50 00:04:18,190 --> 00:04:32,810 , которая принимает указатель и просто делает * р = 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 (р); я передаю указатель в функции Foo 56 00:05:00,770 --> 00:05:03,910 , а затем Foo делает * р = 6; 57 00:05:03,910 --> 00:05:08,600 Таким образом, внутри этой функции, * р-прежнему эквивалентно х, 58 00:05:08,600 --> 00:05:12,720 но я не могу использовать х внутри этой функции, потому что это не областью в этой функции. 59 00:05:12,720 --> 00:05:19,510 Так * р = 6 является единственным способом я могу получить доступ из локальной переменной другую функцию. 60 00:05:19,510 --> 00:05:23,600 Или, хорошо, указатели являются единственным способом я могу получить доступ к локальной переменной из другой функции. 61 00:05:23,600 --> 00:05:31,600 [Студент] Допустим, вы хотели возвращать указатель. Как именно вы это сделали? 62 00:05:31,600 --> 00:05:44,270 [Боуден] Возвращает указатель, как в нечто вроде Int у = 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 и здесь у вас есть адрес памяти, 4 гигабайтами или от 2 до 32. 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 Отказ от ответственности: Anywhere с 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 Да. Я вернусь к этому в секунду. 94 00:08:06,180 --> 00:08:12,220 Во-первых, возвращаясь к возвращению и почему у плохая вещь, 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 и так, что второй вызов баре собирается получить свой фрейм стека. 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 Так где же у живете? 110 00:09:33,790 --> 00:09:36,900 [Студент] у живет в баре. >> [Боуден] Да. 111 00:09:36,900 --> 00:09:45,010 Где-то в этом маленьком квадрате памяти квадратных Литтлер, который имеет у в нем. 112 00:09:45,010 --> 00:09:53,370 Когда я вернусь, и у, я возвращаю указатель на этот небольшой блок памяти. 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 >> [Студент] Так что если вы делали вернуться и у, что стоимость может быть изменена без предварительного уведомления. 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 * у = таНос (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 Но, допустим, мы, случается, называют некоторые другие функции, Баз. 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 Это будет изменились только потому, что вы вызвали функцию Баз. 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 Итак, когда вы хотите вернуть указатель, это где таНос приходит в использовании. 144 00:12:00,930 --> 00:12:15,960 Я пишу на самом деле просто вернуть таНос (3 * SizeOf (INT)). 145 00:12:17,360 --> 00:12:24,050 Мы пройдемся по таНос еще в секунду, но идея таНос это все локальные переменные 146 00:12:24,050 --> 00:12:26,760 всегда идут в стек. 147 00:12:26,760 --> 00:12:31,570 Ничего, что malloced идет по куче, и он будет вечно и всегда быть в куче 148 00:12:31,570 --> 00:12:34,490 пока вы явно освободить его. 149 00:12:34,490 --> 00:12:42,130 Таким образом, это означает, что когда вы таНос что-то, она собирается выжить после возврата из функции. 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 [Студент] Так таНос создает указатель? >> Да. 155 00:13:04,190 --> 00:13:13,030 Malloc - >> [студент] Я думаю, что таНос обозначает блок памяти, который можно использовать в качестве указателя. 156 00:13:15,400 --> 00:13:19,610 [Боуден] Я хочу, чтобы схема снова. >> [Студент] Таким образом, эта функция работает, правда? 157 00:13:19,610 --> 00:13:26,430 [Студент] Да, таНос обозначает блок памяти, который можно использовать, 158 00:13:26,430 --> 00:13:30,470 а затем возвращает адрес первого блока этой памяти. 159 00:13:30,470 --> 00:13:36,750 >> [Боуден] Да. Итак, когда вы таНос, вы захват некоторых блок памяти 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 так, то позже позвонить в таНос может использовать эту память, что ранее вы уже освобождены. 166 00:14:00,030 --> 00:14:09,950 Главное о таНос и бесплатно, что она дает вам полный контроль 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 Malloced память жива, когда вы хотите, чтобы он жив 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 х, памяти выделяется для внутр х. 177 00:14:46,910 --> 00:14:51,630 При х выходит из области видимости, память будет утилизирован для х. 178 00:14:51,630 --> 00:14:54,790 Тогда есть динамическое управление памятью, что и таНос есть, 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 но не того, чтобы иметь, если заявление или заявление во время или что-то в этом роде? 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 у = 3;}. 191 00:15:45,900 --> 00:15:48,440 Это должно быть здесь. 192 00:15:48,440 --> 00:15:52,450 Но это полностью определяет сферу Int у. 193 00:15:52,450 --> 00:15:57,320 После того, что второй фигурной скобкой, у не может быть использована больше. 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 Вы выделении некоторых кусок оперативной памяти для этой переменной. 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 фактических вещей на память. 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 10000. 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 Скажем, у вас есть компьютер с 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 Вот почему указателей 8 байт, поскольку 32 бит 8 байт - или 4 байт. 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 в любом месте от Ох0 ОХ 8 f's - FFFFFFFF. 258 00:21:46,330 --> 00:21:49,180 [Студент] Разве вы не говорите, что они 4 байта? >> Да. 259 00:21:49,180 --> 00:21:52,730 [Студент] Тогда каждый байт будет - >> [Боуден] Шестнадцатеричные. 260 00:21:52,730 --> 00:21:59,360 Шестнадцатеричные - 5, 6, 7, 8. Так указателей вы будете всегда видеть в шестнадцатеричном виде. 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 Так что это будет 8 шестнадцатеричных цифр на 4 байта. 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 Это означает, что, насколько он знает, он может обратиться целая 2 до 32 байт памяти. 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 >> Да. >> [Студент] Что бык значит? Почему вы пишете? 273 00:22:51,930 --> 00:22:54,980 Это просто символ шестнадцатеричной. 274 00:22:54,980 --> 00:22:59,590 Когда вы видите номер начинается с быка, последовательные вещи шестнадцатеричное. 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 и долго, как возвращение 4, так что они оба 4 байта. 300 00:24:45,060 --> 00:24:48,070 Есть ли разница между Int и долго, или это одно и то же? 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 стандартная просто говорит, что символ будет вечно и всегда будет 1 байт. 307 00:25:10,470 --> 00:25:19,040 Все, после этого - короткий всегда просто определить как больше или равна символ. 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 И долго долго, больше или равно долго. 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 Ints почти всегда будет 4 байт. 317 00:26:12,070 --> 00:26:15,340 Длинные длинные, почти всегда будет 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-разрядную систему, как Appliance, это будет 4 байт. 321 00:26:34,530 --> 00:26:42,570 Если вы используете 64-разрядную, как много последних компьютерах, это будет 8 байт. 322 00:26:42,570 --> 00:26:45,230 >> Ints почти всегда 4 байта в этой точке. 323 00:26:45,230 --> 00:26:47,140 Длинные длинные, почти всегда 8 байт. 324 00:26:47,140 --> 00:26:50,300 В прошлом целые использованы только быть 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 или длинный долго. Это зависит только от 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 байт. 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 байта, двухместные являются 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 Я думаю - >> [студент] Как долго тоскует? >> Да. Не думаю. Да. 359 00:29:43,660 --> 00:29:45,950 [Студент] На тесте в прошлом году там был вопрос об основной функции 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 [Студент] Я видел одного на другой год. 367 00:30:10,030 --> 00:30:16,220 Это было похоже Верно или нет: действительно - >> О, с файлом.? 368 00:30:16,220 --> 00:30:18,790 . [Студент] Любое С файл должен иметь - [как говорит сразу - неразборчиво] 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 Действительный исполняемый файл должен иметь основную функцию. 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 Так. В файле не должно быть основной функцией на всех. 381 00:31:11,400 --> 00:31:19,220 И на больших базах кода вы увидите тысячи. Файлы с и 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 Он сказал, сделать это компилятор. Правда или Ложь? 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 Это говорит о цели марку утилита для автоматического определения 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 но вы можете написать сделать файл ничего делать. 406 00:33:03,220 --> 00:33:09,150 Вы можете написать сделать файл, так что, когда вы вводите сделать это только компакт-диски в другой каталог. 407 00:33:09,150 --> 00:33:15,560 Я разочарованы, потому что я трека внутри все мои Appliance 408 00:33:15,560 --> 00:33:21,740 а потом просмотреть PDF с Mac. 409 00:33:21,740 --> 00:33:30,720 >> Так что я иду в Finder, и я могу действительно идете, подключиться к серверу, 410 00:33:30,720 --> 00:33:36,950 и сервер подключиться к мое Appliance, а затем я открываю 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 Так что вместо этого я написал сделать файл, который вы должны определить, как он делает вещи. 416 00:34:02,650 --> 00:34:06,130 Как вы делаете в это PDF LaTeX. 417 00:34:06,130 --> 00:34:10,090 Так же, как и любой другой файл марки - или я думаю, вы еще не видели марку файлов, 418 00:34:10,090 --> 00:34:13,510 но у нас есть в прибор файл глобальных марки, которые просто говорит: 419 00:34:13,510 --> 00:34:16,679 если вы компилируете файл C, используйте Clang. 420 00:34:16,679 --> 00:34:20,960 И вот здесь, в моей сделать файл, что я делаю я говорю, 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 Сделать это не компиляция. Это просто выполнения следующих команд в последовательности я указал. 424 00:34:31,880 --> 00:34:36,110 Таким образом, она работает PDF LaTeX, он копирует его в каталог, я хочу, чтобы быть скопирована, 425 00:34:36,110 --> 00:34:38,270 это компакт-дисков в каталоге и делает другие вещи, 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 * х * у - 435 00:35:24,890 --> 00:35:28,130 Это не совсем здесь ничего, я думаю. 436 00:35:28,130 --> 00:35:32,140 Но, как и * х * у, те 2 переменные, которые находятся на стеке. 437 00:35:32,140 --> 00:35:37,220 Когда я говорю, х = таНос (SizeOf (INT)), х-прежнему переменной в стек, 438 00:35:37,220 --> 00:35:41,180 таНос некоторый блок более в кучу, и мы имеющей точки х до кучи. 439 00:35:41,180 --> 00:35:43,900 >> Так что-то в стек указывает на кучу. 440 00:35:43,900 --> 00:35:48,100 Всякий раз, когда вы таНос что-нибудь, вы неизбежно хранить его внутри мыши. 441 00:35:48,100 --> 00:35:55,940 Так что указатель на стек, malloced блока в куче. 442 00:35:55,940 --> 00:36:01,240 Многие люди путают и говорят Int * х = таНос; х в кучу. 443 00:36:01,240 --> 00:36:04,100 Кол-х Что указывает на это в кучу. 444 00:36:04,100 --> 00:36:08,540 х сама находится в стеке, если по каким-либо причинам вы х глобальной переменной, 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 Он ищет вещи, как # # включают в себя и определить, 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, препроцессор проходит через всю программу 463 00:38:06,640 --> 00:38:10,400 и заменяет все экземпляры х с 4. 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 Сначала он собирается составить Python в C, то это будет для компиляции 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 [Студент] Во время компиляции, давайте скажем, что вы сделали # включить 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 библиотеки, которые являются отдельными от cs50.h, 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 И поэтому файлы, которые сборки в целом выходы. О файлах. 503 00:41:15,230 --> 00:41:19,020 А. Вывода файлов, что мы говорили раньше, 504 00:41:19,020 --> 00:41:21,570 как файл не нужно иметь основную функцию. 505 00:41:21,570 --> 00:41:27,640 Любой файл может быть составлен до. Файл вывода тех пор, пока это правильный файл C. 506 00:41:27,640 --> 00:41:30,300 Он может быть составлен до. °. 507 00:41:30,300 --> 00:41:43,030 Теперь, связывая это то, что на самом деле приносит кучу. О файлах и приводит их к исполняемому файлу. 508 00:41:43,030 --> 00:41:51,110 И то, что компоновка делает, вы можете думать о CS50 библиотеку. Файл вывода. 509 00:41:51,110 --> 00:41:56,980 Это уже скомпилированных двоичных файлов. 510 00:41:56,980 --> 00:42:03,530 И так при компиляции файла, ваш hello.c, которая призывает GetString, 511 00:42:03,530 --> 00:42:06,360 hello.c компилируется до hello.o, 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 на самом деле не о файле, но это достаточно близко, что нет никакой принципиальной разницы. 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. с файлами, вы собрать их все. о файлах, 522 00:42:55,970 --> 00:43:00,040 который, вероятно, займет некоторое время, то вы измените 1. с файлом. 523 00:43:00,040 --> 00:43:05,480 Вам только нужно перекомпилировать, что 1. С файла, а затем перелинковки все остальное, 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, грубо. Или же, Big O является приблизительным. 533 00:44:09,410 --> 00:44:15,300 Так что если вы видите, вложенные циклы циклы по сравнению с аналогичным количеством вещей, 534 00:44:15,300 --> 00:44:22,260 Int, как я, я <п; Int J, J <п - >> [студент] п квадрат. >> Он имеет тенденцию быть указан в квадрате. 535 00:44:22,260 --> 00:44:25,280 Если вы тройной вложенный, он, как правило, п кубе. 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 Это легче понять, почему они являются п квадратов и п § п и все, что 539 00:44:41,420 --> 00:44:47,810 потому что я думаю, что была на тест один год, где мы в основном дал вам 540 00:44:47,810 --> 00:44:55,050 осуществление пузырьковой сортировки и сказал: "Что такое время работы этой функции?" 541 00:44:55,050 --> 00:45:01,020 Так что если вы признаете это, как пузырьковой сортировки, то вы можете сразу сказать, п ​​квадрат. 542 00:45:01,020 --> 00:45:05,470 Но если вы просто посмотрите на нее, вам даже не нужно осознать, что это пузырьковой сортировки; 543 00:45:05,470 --> 00:45:08,990 Вы можете просто сказать, что это делать это и это. Это п квадрат. 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 Для каждого элемента массива, который будет что-то, что п в квадрате. 550 00:45:45,370 --> 00:45:49,940 Есть общие вопросы, например, прямо здесь, у нас - Oh. 551 00:45:55,290 --> 00:45:58,530 Буквально на днях, Дуг заявил: "Я изобрел алгоритм, который может сортировать массив 552 00:45:58,530 --> 00:46:01,780 "П чисел в O (журнал 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 так что это невозможно сделать это менее чем за O н. 559 00:46:27,430 --> 00:46:30,340 [Студент] Вы показали нам, что пример в состоянии сделать это в 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 Да. Эти типы видов, которые могут выполнить вещи в большом 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, 4 млн. 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 в возвращении заявления, что это хвост рекурсивной, 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 х) или что-то еще. 579 00:48:42,920 --> 00:48:52,310 Это не идеальный рекурсивной функции, но возвращение бар (х - 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 , что соответствует ее аргумента х. 585 00:49:17,490 --> 00:49:25,840 И так скажем, основной, случается, называют Бар (100); 586 00:49:25,840 --> 00:49:30,050 Таким х собирается начать, как 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 И тогда она будет делать это снова и она достигнет возвращения бар (х - 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 и возвращает его значение в этом, то он просто будет немедленно вернуться 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 [Студент], если бар (х + 1). >> Да. 622 00:52:07,530 --> 00:52:11,770 >> Так что, если вы поместите его в состояние, то вы делаете что-то с возвращаемым значением. 623 00:52:11,770 --> 00:52:16,260 Или даже если вы просто возвращение 2 * бар (х - 1). 624 00:52:16,260 --> 00:52:23,560 Так что теперь бар (х - 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 где бар состоится Int х в у 632 00:52:53,550 --> 00:52:56,990 и у соответствует конечная вещь, которую вы хотите вернуть. 633 00:52:56,990 --> 00:53:03,650 Так вот это вы будете возвращаться бар (х - 1), 2 * у. 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 А потом, в конце концов, когда вы достигнете своей базы случае, вы просто вернуть у 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 При использовании строк, что это легко, потому что строки символов звезды, 643 00:53:48,440 --> 00:53:51,860 символы вечны и всегда один байт, 644 00:53:51,860 --> 00:53:57,540 и так арифметики указателей эквивалентно регулярные арифметических когда вы имеете дело со строками. 645 00:53:57,540 --> 00:54:08,790 Давайте просто скажем, символ * S = "привет". 646 00:54:08,790 --> 00:54:11,430 Итак, мы имеем блок в памяти. 647 00:54:19,490 --> 00:54:22,380 Она нуждается в 6 байт, потому что вы всегда должны нулем. 648 00:54:22,380 --> 00:54:28,620 И символ * 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 независимо от того, было ли это возвращение таНос или это в стеке. 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 >> Поэтому, когда я говорю что-то вроде с [3], это будет ей и подсчет 3 символа дюйма 655 00:55:05,360 --> 00:55:12,490 Таким образом, с [3], мы имеем 0, 1, 2, 3, таким образом, с [3] будет ссылаться на эту л. 656 00:55:12,490 --> 00:55:20,460 [Студент] И мы могли бы достичь такого же значения, делая с + 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 х [4] >> [студент] Значит ли это, создайте памяти? 665 00:55:53,630 --> 00:56:03,320 [Боуден], что собирается создать 4 целых чисел в стеке, поэтому 16 байт в целом. 666 00:56:03,320 --> 00:56:05,700 Он собирается создать 16 байт в стеке. 667 00:56:05,700 --> 00:56:09,190 х нигде не сохраняется. 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 что компилятор будет сделать, это просто заменить все вхождения переменной х 671 00:56:22,340 --> 00:56:26,400 с, где это произошло выбрать, чтобы положить эти 16 байт. 672 00:56:26,400 --> 00:56:30,040 Он не может сделать это с помощью символов * потому, что ей это фактически указатель. 673 00:56:30,040 --> 00:56:32,380 Это бесплатно, чтобы потом указать на другие вещи. 674 00:56:32,380 --> 00:56:36,140 х является постоянным. Вы не можете иметь его точки к другой массив. >> [Студент] Хорошо. 675 00:56:36,140 --> 00:56:43,420 Но эта идея, эта индексация, такое же, независимо от того, является ли это традиционным массивом 676 00:56:43,420 --> 00:56:48,230 или, если это указатель на что-то или, если это указатель на malloced массива. 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) или с [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 х [3] [3], это действительно только 1 массив с 9 значений. 685 00:57:55,500 --> 00:58:03,000 И поэтому, когда я индексом, компилятор знает, что я имею в виду. 686 00:58:03,000 --> 00:58:13,090 Если я скажу, х [1] [2], он знает, я хочу пойти на второй строке, так что он собирается пропустить первые 3, 687 00:58:13,090 --> 00:58:17,460 , а затем она хочет Второе в том, что так оно собирается получить это. 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 * р = х; 691 00:58:29,770 --> 00:58:33,220 Тип х просто - 692 00:58:33,220 --> 00:58:38,280 Это грубо говоря типа х, так как это всего лишь символ, и это не фактической переменной, 693 00:58:38,280 --> 00:58:40,140 Но это всего лишь Int *. 694 00:58:40,140 --> 00:58:44,840 х это просто указатель на начало этого. >> [Студент] Хорошо. 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 (* р [-. что-то абсолютно смешно, я даже не знаю. 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 Да. >> [Студент] Скажем, у вас есть очень длинный массив. 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 , который, если мы посмотрим на здесь скажем, это наша память, 722 01:01:09,010 --> 01:01:16,600 если у меня есть 2 гигабайта оперативной памяти, это действительно адресу 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 Это одна может соответствовать этим сюда. 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 Струны были легче, но, глядя на то, как целыми, 737 01:02:28,410 --> 01:02:35,000 Итак, вернемся к Int х [4]; 738 01:02:35,000 --> 01:02:41,810 Является ли это массив или это указатель на malloced массив из 4 чисел, 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 х [4]; 745 01:03:16,280 --> 01:03:22,520 Он собирается создать 4-целое число блоков в стеке для этого массива. 746 01:03:22,520 --> 01:03:26,960 Но это таНос (4 * SizeOf (INT)); будет идти в кучу. 747 01:03:26,960 --> 01:03:31,870 Но после этого момента я могу использовать х и р в значительной степени теми же способами, 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 Р я могу сказать, р [3] = 2, или х [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 [Студент] Вы не должны делать р * если у вас есть скобки? 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 ** рр = таНос (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 Что я сделал здесь - Это должно быть рр [I]. 762 01:05:48,910 --> 01:05:53,680 Так п.п. это указатель на указатель. 763 01:05:53,680 --> 01:06:02,420 Вы mallocing п.п. указывает на массив из 5 звезд Int. 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 А потом, когда я таНос сюда, я таНос, что каждый из этих отдельных указателей 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 байт. 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 Я мог бы сказать п.п. [3] [4], но теперь это не то же самое, многомерные массивы 773 01:06:58,030 --> 01:07:05,390 потому что многомерные массивы в ее переводе [3] [4] в одну смещение в массиве х. 774 01:07:05,390 --> 01:07:14,790 Это разыменовывает р, доступ к третьему индекса, то, что разыменовывает 775 01:07:14,790 --> 01:07:20,790 и доступы - 4 будут считаться недействительными - второй индекс. 776 01:07:24,770 --> 01:07:31,430 В то время, когда мы были Int х [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 ***** р. 789 01:08:18,050 --> 01:08:23,760 Вернуться к арифметике с указателями - >> [студент] Ох. >> Да. 790 01:08:23,760 --> 01:08:35,649 [Студент] Если у меня есть Int *** р а затем я разыменование, и я говорю р * равна этому значению, 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 Тогда вы *** р. >> Хорошо. 794 01:08:46,210 --> 01:08:54,080 Так что это р указывает на 1 блок, указывающий на другой блок, указывающий на другой блок. 795 01:08:54,080 --> 01:09:02,010 Тогда, если вы делаете * р = что-то другое, то вы меняете эту 796 01:09:02,010 --> 01:09:13,640 Теперь, чтобы указать на другой блок. >> Хорошо. 797 01:09:13,640 --> 01:09:17,649 >> [Боуден] И если они были malloced, то вы теперь утечка памяти 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 х [4]; собирается выделить массив из 4 чисел 802 01:09:36,310 --> 01:09:40,670 где х будет указывать на начало массива. 803 01:09:40,670 --> 01:09:50,420 Поэтому, когда я говорю что-то вроде X [1], я хочу, чтобы это означало идти на второй целое число в массиве, 804 01:09:50,420 --> 01:09:53,319 , который был бы этому. 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 Это массив целых чисел, поэтому он знает, что нужно делать 1 раз размер Int, когда он хочет, чтобы компенсировать. 809 01:10:17,170 --> 01:10:25,260 Другой синтаксис. Помните, что это эквивалентно * (х + 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 Таким образом, если х = ox100, то х + 1 = ox104. 813 01:10:59,510 --> 01:11:19,750 И вы можете злоупотреблять этим и сказать что-то вроде символ * C = (символ *) х; 814 01:11:19,750 --> 01:11:23,050 и теперь с будет тот же адрес, х. 815 01:11:23,050 --> 01:11:26,040 С будет равна ox100, 816 01:11:26,040 --> 01:11:31,490 но с + 1 будет равна ox101 817 01:11:31,490 --> 01:11:38,030 С арифметикой указателя зависит от типа указатель, который вы добавляете в. 818 01:11:38,030 --> 01:11:45,390 Таким образом, с + 1, он смотрит на C, это символьный указатель, так что он собирается добавить 1 раза размер символов, 819 01:11:45,390 --> 01:11:48,110 который всегда будет на 1, так что вы получите 101, 820 01:11:48,110 --> 01:11:54,890 а если я сделаю х, которая также еще 100, х + 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 Вы не можете сделать этого, потому что с х х это просто символ, это постоянная, вы не можете изменить х. 824 01:12:16,180 --> 01:12:22,610 >> Но с происходит, чтобы быть просто указатель, так что C + + является вполне допустимым, и она будет увеличиваться на 1. 825 01:12:22,610 --> 01:12:32,440 Если с просто Int *, то C + + будет 104. 826 01:12:32,440 --> 01:12:41,250 + + Делает арифметику указателей так же, как с + 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 Скажем, я хотел бы передать эту сторону массива в функцию. 831 01:13:10,520 --> 01:13:12,700 Что бы я передать эту функцию? 832 01:13:12,700 --> 01:13:17,050 Если я прохожу х, я передаю этот адрес. 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 [Боуден] Таким образом, х + 2. Да. 836 01:13:29,350 --> 01:13:31,620 Это будет этот адрес. 837 01:13:31,620 --> 01:13:42,810 Вы также очень часто вижу это как х [2], а затем адрес этого. 838 01:13:42,810 --> 01:13:47,850 Таким образом, вы должны взять на адрес, потому что кронштейн неявных ссылок. 839 01:13:47,850 --> 01:13:53,250 х [2] ссылается на значение, которое находится в этом поле, а затем вы хотите адрес этого окна, 840 01:13:53,250 --> 01:13:56,850 так что вы говорите и х [2]. 841 01:13:56,850 --> 01:14:02,880 Так вот, как что-то сортировки слиянием, где вы хотите передать половину списка, чтобы что-то 842 01:14:02,880 --> 01:14:08,790 Вы действительно просто передать и х [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 [Студент] Если мы не будем ставить амперсанд или - что, что называется? >> Star? 846 01:14:20,050 --> 01:14:23,200 [Студент] Star. >> Технически, оператор разыменования, но - >> [студент] Dereference. 847 01:14:23,200 --> 01:14:29,310 >> Если мы не ставим звезды или амперсанд, что произойдет, если я просто скажу, у = х и х является указателем? 848 01:14:29,310 --> 01:14:34,620 Какой тип у? >> [Студент] Я просто говорю, что это указатель 2. 849 01:14:34,620 --> 01:14:38,270 Так что если вы только что сказали у = х, теперь х и у указывают на одно и то же. >> [Студент] указывают на то же самое. 850 01:14:38,270 --> 01:14:45,180 И если х 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 * х - действительно все х хранения что-то вроде ox100, 854 01:15:02,010 --> 01:15:06,490 которые мы, случается, представляющих как указание на блоке хранится 100. 855 01:15:06,490 --> 01:15:19,660 Поэтому когда я говорю Int * у = х, я просто копирование ox100 в у, 856 01:15:19,660 --> 01:15:24,630 которые мы только собираемся представить как у, также указывая на ox100. 857 01:15:24,630 --> 01:15:39,810 И если я говорю Int я = (INT) х, тогда я намерен хранить любые значения 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 Это собирается быть литья Int х или литье Int у? 862 01:16:00,290 --> 01:16:03,700 [Боуден] Что? 863 01:16:03,700 --> 01:16:07,690 [Студент] Хорошо. После этих скобках там будет х или ау там? 864 01:16:07,690 --> 01:16:11,500 >> [Боуден] Либо. х и у являются эквивалентными. >> [Студент] Хорошо. 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 * х = 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 Так что я свободно копировать ox100 от Int * в целое число, 876 01:17:02,920 --> 01:17:07,790 и я свободно назначать - ты, вероятно, собираюсь кричать на что не литье - 877 01:17:07,790 --> 01:17:18,160 Я свободен назначить что-то вроде (Int *) ox1234 в этой произвольной * Int. 878 01:17:18,160 --> 01:17:25,480 Так ox123 так же верен адрес памяти, как это и у. 879 01:17:25,480 --> 01:17:32,060 И у случается, вернуть то, что является в значительной степени ox123. 880 01:17:32,060 --> 01:17:35,430 [Студент] Это было бы действительно здорово путь от шестнадцатеричной в десятичную форму, 881 01:17:35,430 --> 01:17:39,230 нравится, если у вас есть указатель, и вы бросили его в виде целого числа? 882 01:17:39,230 --> 01:17:44,860 [Боуден] Вы действительно можете просто печатать, используя как Printf. 883 01:17:44,860 --> 01:17:50,300 Скажем, у меня есть Int у = 100. 884 01:17:50,300 --> 01:18:02,700 Таким образом, Е (% г \ п - как вы уже знаете - печать, что как целое, х%. 885 01:18:02,700 --> 01:18:05,190 Мы просто распечатать его как шестнадцатеричное. 886 01:18:05,190 --> 01:18:10,760 Таким образом, указатель не хранится в шестнадцатеричном, 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 Это только, что мы, как правило, чтобы показать, указатели, как шестнадцатеричное 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 Так что это просто наша интерпретация указатели, как шестнадцатеричное. 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]