Арифметика указателей. Указатели и массивы. Массив это указатель. C++ для начинающих. Урок #47
HTML-код
- Опубликовано: 16 июл 2017
- Понравилось видео или оказалось полезным? Подпишись!
Арифметика указателей. Указатели и массивы. Массив это указатель. C++ для начинающих. Урок #47
Уроки по программированию
Наша группа ВК smplcode
Подписывайтесь на канал / @simplecodeit
Арифметика указателей приводит к следующему:
a[i]= *(a+i) = *(i+a) = i[a]
Т.е. в записи кода можно менять местами имя массива и значения индекса элемента в квадратных скобках. Т.е. записи a[3] и 3[a] равноценны. поясню на примере, например есть массив int a[] = { 1,3,5,7,9,11 };
тогда a[3]=7 . Если записать в коде 3[a] то тоже получим 7
Это приводит к парадоксальным записям кода, которые программисты не используют, но на собеседованиях их могут попросить пояснить. Например, задачка:
что выведется на экран из такого :
int a[] = { 4,3,5,7,9,11 };
int a2 = 3[a+1]-a[5]+(a-1)[4];
cout
Sasa ааааааааааааа!!!!!!!!!!!!!! Но я понял. Но ААаАааАаАаАа!!!!!!!!!!!! Я проверил твой пример, потом по аналогии шлепнул свой. Сначала это взорвало мне мозг а пото взорвало ещё раз. Спасибо это круто!
Крышу сносит
Это просто... мне понравилось, пример такой же классный, как автор этого ролика
я так понимаю это танется из расчета адресов в ассемблере по начальному адресу и индексам сдвига.
@Negative 3 -- это порядковый номер числа в массиве, а -- это нулевой элемент массива т.е. цифра 4, а+1 -- это сдвиг начальной (нулевой) позиции массива на один вперед (+1) т.е. в этом случае нулевым элементом станет тройка, первым - 5, вторым - 7, а ТРЕТЬИМ - 9.
Вроде все ясно, но такое чувство что я что-то упускаю)
Все равно спасибо большое за урок!
я долго, думал, не писать комментарий. Но тут трудно не заметить. Уровень БОГ. Четко и ясно. Вопросов вообще не остается. БОООЖЕЕЕСТВЕЕЕННОО. Реально, материал(урок) - БОМБА. Мощно. Нет слов, в хорошем смысле. Реально, я хоть и атеист, но я ,наверное, начну на Вас молиться =)))) Реально классные уроки, аплодирую стоя. Браво =)
Неверующий:)?
@@petroalex5816 так и есть:))
как сейчас дела ?
Только решил уверовать и тут же ошибка
Не создавать себе идолов и кумиров)))
😁😁😁
Если у тебя вопросов не остается, то это очень плохо, значит ты плохо понял тему, так как там много нюансов.
ох как же не просто это усвоить и применить то сразу ((
спасибо за уроки огромное
Классный урок. и весь плейлист, спасибо автору. Жалею что не просмотрел его три года назад.
0:35 - Создаем, заполянем и выводим массив
1:27 - Создаем указатель и присваиваем ссылку на массив *pArr = arr;
1:57 - Вывод массива arr циклом for с помощью указателя *pArr; // cout
Большое спасибо за видео, Сергей! Доступно, внятно и доходчиво!
Как же хорошо и понятно вы все объясняете ! Благодарю
Лучшие и самые доступные видеоуроки по С++, спасибо огромное!
Долго искал информацию по указателям и всё равно не очень понял эту тему, но Вы всё объяснили максимально просто и понятно, спасибо огромное за Ваши труды!
хороший монтаж , классные вставки , биг респект и лайк
Уроки прекрасные! Спасибо))))
Как буд-то к ассемблеру ведете) А так спасибо!
Очень понравилось изложение! Большое спасибо!
Вы лучший. Спасибо!
Отличный ролик, а также взорвал мозг комментарий пользователя Sasa, его пример это реально снос башки!
Мне очень понравился этот урок, интересно было поэкспериментировать с памятью, массивами, указателями и так далее
спасибо за уроки) учусь в академии там те же темы проходим, когда что то не понятно смотрю все понятно становится))
Спасибо за этот доходчивый урок
Интересно, спасибо!
Спасибо вам за ваши видео. Хочу чтобы ваш канал полетел вверх по просмотрам и лайкам, лично я бы поставил бы тонну( к сожалению не имею такой возможности). В общем желаю вам удачи и еще раз очень благодарен вам, счастья и здоровья!
спасибо большое!!!
Спасибо.
Вот почему массивы начинаются с нуля. Спасибо!
Спасибо, в 2 словах объяснили всю лекцию
* Самые понятные, видео уроки по c++, на всём (RU) youtube *
Спасибо!
Спасибо за урок !!!
Супер. Всё было понятно.
сердечно благодарю, товарищ)
крутая ава
очень полезен урок, спасибо большое)))))))))))))))))
спасибо за урок!)
но я немного не понял первую часть ролика с 1:40 по 4:15!
когда будем проходить динамические массивы будет более понятно.
Хотела спать, включила видео, смотрела в сонном состоянии
Видео закончилось, я поняла то, что все поняла и даже как-то взбодрилась
Редко такие ощущения получаю от учебы
Сергей - золотой человек, за несколько уроков поняла тему, которую невтупляла пол года. мужик сас
серьезно?
@@novattruldax1970 да
Лучший!
Шикарно. Смотрел на другом канале, вообще ничего не мог понять, что за указатели!
Сергей не указал маленькую но важную фишку, и здесь и в теме о инкрементах.
Взаимодействие инкремента и указазателя: arr[I + 1] и arr[I++] разные вещи
Пример в коде:
#include
using namespace std;
void Print(int *arr)
{
for (int i = 0; i < 3; i++)
{
cout
Это прикол 1-е вы создали функцию для вывода массива в консоль. 2-е создали 2 массива (arr1 и arr2) и переменную " j " со значением ноль(" 0 "). 3-е запустили функцию Print и вывели в консоль массив arr1. (3, 2, 1). 4-е arr1[j + 1] = arr1[j]; присвоили элементу с индексом " 1" (arr1[j + 1]) значение элемента с индексом " 0'" (arr1[j] .Как у вас получилось J + 1 = 0 я не знаю. Должно быть " 1 ". 5-е . Запустили функцию Print(arr1); и 3 3 1
Массив изменился потому что вы переписали значение элемента с индексом " 1". 6-е Запустили функцию Print(arr2); получили 3 2 1 7-е arr2[j++] = arr2[j];
Присвоили элементу с индексом " 0 " значение " 3" Как это произошло?
У постфиксного инкремента самый низкий приоритет выполнения фактически вы сделали arr2[0] присвоили arr2[j] (" 3") и J++ = 1 ( в место " 1 " должно быть 0) Запустили функцию Print(arr2) и в итоге 3 2 1 Массив остался прежним И указатели здесь не причём. Массив и так передается по ссылке. здесь вы не создавали указателя и здесь нет арифметики указателей и посмотрите урок 34( с этого надо было начать, но как получилось , так получилось).
Спасибо 👆👍
Спасибо
Ты просто лучший
Спасибо 😉
Благодарю, интересный урок. Хотя по мне удобнее индекс использовать, для меня это нагляднее
Открытие!
я имел ввиду, все уроки бомба. Автоматически лайк, не глядя =) Огромное спасибо=)
спасибо!
Автор крут!
ля как интересно, лайк
Сначала не понял почему
cout
Спасиииииибоооооооооооооооо БОЛЬШОЕЕЕЕЕЕЕЕЕЕЕЕЕЕЕ !!!!!!!!!!!!!!!!!!!
#указатели #арифметикауказателей #SimpleCode #урокипрограммирования
пожалуйста =)
Сергей, а какой у вас стаж работы кодером с++
Годно
спасибо
Есть еще один важный момент по арифметике указателей, мы можем складывать и вычитать указатели одного типа. И если мы к указателю прибавляем например единицу, то адрес смещается на длину типа указателя, с вычитанием также. Можн еще указатели вычитать друг из друга.
Имя массива является указателем на адрес его первого элемента.
об этом не многие говорят на видеоуроках
Первый элемент массива цифра 4?
Paint Это наше все :!)
однозначно =)
Я когда играл раньше в героев меча и магии 3 всегда любил ArtMoney в области памяти игры искать интовые 4х байтные значения количества армии в слоте и путем перезаписи значения адреса переменной ломал игру на количество монстров в слоте 😅
Почему когда мы выводим pArr[i] мы не разыменовываем его?? По идее же мы должны получить адрес i-того элемента ,а не его значение
Тоже интересует ответ на этот вопрос, либо такой синтаксис, либо я что-то упускаю. Прошу знающих подсказать, спасибо
Потому что название массива, это указатель на его первый элемент
pArr[i] это так называемый синтаксический сахар. Аналогично *(pArr +i). Разыменование уже используется. pArr[i] более удобно использовать и вариант более приемлем
Не понял момент с магией. То есть имя массива (arr) указывает на первый элемент (4)?
Гуд )
привет из 2023. Спасибо большое!
я правильно понял что в Java невозможно выйти за границы массива - сразу исключение выбросится, а в с++ без проблем???
👍
int *pArr=arr;
Почему мы ту так пишем ? Разве мы не адрес массива даем ? Если адрес то почему нет & впереди массива? Объясните пожалуйста.
И почему при обращения к элементу массива мы не разименуем сначало символом "*" как простую переменную ?
cout
Ну смотри 1. Мы указываем на указатель. То есть мы указываем массиву, а массив указывает на индексы
2. Потому что pArr - это указатель и он указывает уже на сами индексы
Думаю вовремя ответил
Эх жалко Сергей пропал...
Здравствуйте
Спасибо огромное за уроки, смотрю все по порядку, очень здорово преподносите.. Огромный труд.. Очень благодарен
Возник вопрос, понимаю что прошло много времени с записи видео , но был бы очень благодарен , если бы вы ответили, очень волнует меня этот вопрос и мешает пониманию..
1.В конце видео все сломалось , и это вроде как хорошо, но почему сломалось? в памяти же должно быть какое - то число ? или информация ? получается его просто не было ? а если бы было программа бы взяла? или нету такого адреса?
почему не получилось взять какое - либо число , которое находилось в памяти в тот момент?
Привет:) Ответа на вопрос не знаю:( Но хотел поинтересоваться, как у тебя сейчас дела с с++ ?
@@faust8th316
привет , все хорошо, почему спрашиваешь ? смогу ответить более подробно тогда
@@sergeyv7342 да, можно попродробнее. просто интересно узнать, как дела с языком у людей по прошествии нескольких месяцев или лет.
А то кого не спросишь, у большинства аккаунты заброшены:(
Ячейка памяти может быть как занята данными так и нет (т.е не ссылаться ни на что(NULL)) чаще всего место не занято т.к программа не большая и памяти много не займет.
Массивы - это быстро и весело!
Спсб
Благодаря тебе понял ещё одну деталь, огромное спасибо, но есть недочёты, которые кусают за задницу в начале.
тоесть масив работает как побитовый сдвиг вправо, с шагом в количество бит которые определяет тип переменной масива? поэтому он и начинается с нуля.
масив указывает на первую переменную а потом сдвигает в право или в лево на шаг размером типа переменной. это много чего обясняет
А можно работать как-то без указателей? К примеру, как в Фортране или Бейсике?
Уроки просто огонь
Но вот чего понять не могу: допустим, мы объявили и инициализировали интовый массив arr[ ] (без использования SIZE, просто прописали все элементы в фигурных скобках ).
Допустим, в массиве три элемента т.е. его размер в байтах 3*4(размер int) = 12.
Тогда каким образом sizeof(arr) возвращает 12, если массив в функцию передается по ссылке?
Или это уже особенности работы компилятора и ключевого слова sizeof() ?
Так, вроде разобрался
Происходит это из-за того, что массив статический.
Но если кто-то даст более глубокий ответ - буду благодарен ;)
Если операндом является выражение, то sizeof возвращает суммарный объем памяти, занимаемый всеми переменными и константами, входящими в него. Если операндом является массив, то возвращается объем памяти, занимаемый всеми элементами массива (т.е. имя массива не воспринимается в данном случае как указатель). Число элементов в массиве можно определить выражением sizeof array/sizeof аrrау[0].
Супер урок!
Есть один украинский канал где тоже качественный курс по с++.
Но эта тема здесь лучше раскрыта☝🏻
А як називається? Я щось не знаю укр каналів про прогу(
@@user-pc7do4wr7q Блоган в ютубі вбийте👌🏻
11:43 Нам повезло - программа не работает! В - везение)
Стоило добавить, что имя массива является обязательно константным указателем, т.е. операции *(arr++), как и другие преобразования указателя-имени массива невозможны, в отличие от операции *(arr+i) и т.п.
Спасибо за урок! Трудно для понимания, конечно, но со скрипом извилин что-то да и понимаю!..
Вопрос появился. Могу ли я хранить слово в виде указателя, просто сдвигая на 1 sizeof(char) каждый раз, когда читаю новый символ, а в конце занулять ячейку ? По сути массив, даже string, только резиновый (по размеру)
Спрашиваю, потому что не вижу здесь минусов. Но вроде бы каждая структура обладает обеими сторонами медали)
Хранить где?
Почему значение pArr[i] показывает значение, вместо адреса
Ведь вроде
pArr[i]- адресс
*pArr[i]-значение этого адресса
Если я верно понимаю, то используя квадратные скобки [], указатель уже разыменовывается (неявно) и превращается в значение.
pArr[i] -> *(pArr + i). если i = 0, то будет просто *pArr а это уже значение 1 элемента массива. ну и тд
Спасибо есть одна идейка как использовать выделенную память
// генератор случайных чисел основанный на разнице ячеек динамической памяти
#include
using namespace std;
int main()
{
setlocale(LC_ALL, "Rus");// Русификатор
int i=0; // отдельная переменная для считывания цикличности
// создаем указатели для резервирования памяти
int *pa = new int; // задаем случайный новый адрес для pa
int*pb = new int;// задаем случайный новый адрес для pb
if (pa
Этот код не работает. К тому же код еще плох тем что вы не освобождаете память операцией delete.
int *pa = new int; // задаем случайный новый адрес для pa int*pb = new int;// задаем случайный новый адрес для pb - адреса не будут новыми - они при одном и том же запуске - одинак.
У меня возник вопрос. Если при записи *(arr + i) программа делает сдвиг на количество байт сообразно типу данных i, не получится ли какая-то ошибка в случае, когда массив имеет другой тип данных (double, к примеру)?
п.с. отдельное спасибо за Ваши уроки, они лучшие❤️
В этом случае i должна иметь тот же тип данных, что и данные в массиве. Так как int имеет размер 4 байта, то запись arr + i сдвигает на 4 байта, таким образом мы переходим к следующей ячейке памяти, где тоже хранится int'овое значение.
Поэтому если нужно оперировать типом данных double, i должна быть тоже double, чтобы счётчик ровно отсчитывал ровно 1 ячейку.
@@user-fl6jp7zq2i не говорите бред.
А есть индекс со значением " 1.5 ?
@@user-fl6jp7zq2i А есть индекс со значением " 1.5 ?
cout
Так как имя массива - указатель, то и работать с ним можно как с указателем, например:
1) cout
@@BadDanFeeds "1) cout
Я думаю самая не понятная ситуация с типом String. Объясните пожалуйста сколько памяти выделяется на один элемент.
Если string реализован действительно классом, то наверное прилично, так как там должны быть свои всякие поля с типами данных которые тоже имеют размеры
На 2:33 Я не понял
Мы в указатель записали адрес первого элемента массива pArr = arr;
А потом, в цикле, мы обращаемся к указателю, как к массиву указателей pArr[i]
Но мы же не создавали массив указателей. К тому же мы записали в него только адрес первого элемента массива, откуда появляется доступ к остальным элементам?
Подскажите пожалуйста
5:23 - массив - это непрерывная область памяти. Вот так и получаешь доступ к другим ячейкам
я понял так. Этой строкой мы задаем, что значение первого элемента массива pArr надо брать по адресу первого элемента массива arr. В таком случае другие элементы тоже берутся соответственно с других ячеек с шагом 4 бита. Размер массива вообще судя по всему пофиг)). Можешь отсканировать всю оперативу)))). Ой ой - дальнейший ход мысли лучше не озвучивать в эфире. Веселый С++)))
Попытался написать одномерный массив типа char. Объясните, пожалуйста, что не так. Почему пробелы игнорируются и выводятся только первые 10 символов?
int main()
{
cout *(line+i);
size+=1;
}
cout
хз
Ну я конечно незнаю, но ты забыл удалить динамический массив может в этом проблема
все что связано с указателями одинаково в Си и С++ ? уроки по указателям в С++ подходят для Си?
логика да однозначно подходит, но синтаксис в некоторых моментах могут быть другой.
up
int элемент массива весит 4 байта => Если интовый (int) массив начинался с 0FD0000, к примеру, то прибавив к адресу 4 (0FD0004) получим второй элемент массива?
Просто я делал такую вещь: cout
Это адреса в 16 ричной системе а не число само
@@poloston3583 адреса меняются в оперативе при каждом новом запуске программы
Тоесть если имя массива это указатель на первый елемент,то вывод такой:массив хранит адреса в которых есть значения и что это указатель который хранит несколько адресов?
Нет, указатель хранит только один адрес, но добавляя, например, 1 к этому адресу, мы делаем отступ в памяти с шагом, который зависит от того, на какой тип данных указывает указатель.
6:18 Перекопал весь инет и не нашел чтоб настроить по умолчанию горячими клавишами коментировать /**/. Все что-то умничают некой чушью, но чтоб нажать гор.клавишу на выделенный текст и закоментить /**/ - нет. Подскажите как это сделать, так как вижу это на этом видосе.
Ctrl+C
@@nicistey3895 Ctrl K затем Ctrl C
А Ctrl K, затем Ctrl D форматирует файл (выравнивает код)(только не выделенный фрагмент, а сразу во всём файле)
it is magic
Я не могу понять. В цикле for мы переменной i двигаемся по массиву, но почему, если i = 2, сдвиг происходит все равно на 4 байта, а не на 8?
на 8. ты забывешь что у тебя i=2 это третий элемент и он указывает на адрес начала третьего элемента
#include
#include
using namespace std;
int main()
{
int arr[3];
for (int i = 0; i < sizeof (arr)/sizeof(int); i++)
{
cout
до какого урока мне нужно посмотреть, чтобы начать писать на Unreal Engine???
С таким подходом, тебе лучше на блюпринтах работать, зачем себя мучаешь с плюсами?
Если имя массива - это действительно указатель на его первый элемент, то почему sizeof(arr) != sizeof(&arr[0]), то есть почему sizeof возвращает размер всего массива, а не размер указателя?
Потому что массив (статический) это все-таки не указатель. Они очень тесно связаны, но это не одно и то же. И разное поведение sizeof это красноречиво подтверждает.
Массив превращается в указатель (сравнивается с указателем) в двух случаях - при применении оператора доступа (например a[0], что то же самое что *(a+0)) и при передаче в функцию.
мне удалось получить значение из адреса за пределами массива, прога не крашнулась.
запишите что нибудь за пределы проги
@@user-ne4bd3ry1n Крашните хром. Ибо вся оперативка явна у него))
А можно и так пробежаться по массиву)
int arr[5] = {10, 20, 30, 40, 50};
for(int* p = arr; p < arr + 5; ++p)
cout
Добрый день, хочу спросить прошли ли вы курс до конца?
@@maksimboiko007 Вы про эти видео? Эти видео подходят лишь для закрепления уже изученного материала, да и то в них мало информации. Советую читать книги)
я теперь понял почему масивы и в фунции не меняли значения
Можно сойти с ума и использовать px[0] в качестве разименования!
Посоветуйте литература по c+c, пожалуйста
Страуструп. Сам создатель языка написал книгу
=2c
Кто подскажет, пожалуйста, почему ошибка C2440:
#define N_rows 3
#define N_cols 3
int arr[N_rows][N_cols];
int *ptr_a = arr; // Ошибка C2440 инициализация: невозможно преобразовать "int [3][3]" в "int *"
Спасибо.
Так как имя массива является указателем, то у вас получается указатель на указатель. Если разименовать массив, то ошибки не будет: int *ptr_a = *arr;
@@borisblade1403 Спасибо, наконец то избавился от ошибки с двумерным массивом. Но почему тогда у автора с одномерным массивом в 18 строке эта ошибка не вылезает? Ведь и у него arr - это имя массива и является указателем?
фааааааааааак! Я раньше сток времени тратил на то, чтобы массив в функцию запихать
Ths
Тааак, що ти нам тут приготував...