pu arr extso что значит
Массивы и функции
Массивы, также как остальные переменные, можно передавать в функции в качестве аргументов. Рассмотрим такую программу:
На прошлом уроке мы выяснили, что имя массива — это константный указатель на первый элемент массива; т.е. имя массива содержит адрес. Выходит, что мы передаем в функцию копию адреса, а не копию значения. Как мы уже знаем, передача адреса приводит к возможности изменения локальных переменных в вызывающей функции из вызываемой. Ведь на одну и ту же ячейку памяти могут ссылаться множество переменных, и изменение значения в этой ячейке с помощью одной переменной неминуемо отражается на значениях других переменных.
Описание вида arr[] в параметрах функций говорит о том, что в качестве значения мы получаем указатель на массив, а не обычную (скалярную) переменную типа int, char, float и т.п.
В данном случае параметр n — это количество обрабатываемых элементов массива.
Следует еще раз обратить внимание на то, что при передачи имени массива в функцию, последняя может его изменять. Однако такой эффект не всегда является желательным. Конечно, можно просто не менять значения элементов массива внутри функции, как в данном примере, где вычисляется сумма элементов массива; при этом сами элементы никак не изменяются:
Но если вы хотите написать более надежную программу, в которой большинство функций не должны менять значения элементов массивов, то лучше в заголовках этих функций объявлять параметр-указатель как константу, например:
В этом случае, любая попытка изменить значение по адресу, содержащемуся в таком константном указателе, будет приводить к ошибке и программист будет знать, что функция пытается изменить массив.
Усовершенствуем программу, которая была приведена в начале этого урока:
Указатели в C++ — урок 7
Если переменных в памяти потребуется слишком большое количество, которое не сможет вместить в себя сама аппаратная часть, произойдет перегрузка системы или её зависание.
Если мы объявляем переменные статично, так как мы делали в предыдущих уроках, они остаются в памяти до того момента, как программа завершит свою работу, а после чего уничтожаются.
Такой подход может быть приемлем в простых примерах и несложных программах, которые не требуют большого количества ресурсов. Если же наш проект является огромным программным комплексом с высоким функционалом, объявлять таким образом переменные, естественно, было бы довольно не умно.
Можете себе представить, если бы небезызвестная Battlefield 3 использовала такой метод работы с данными? В таком случае, самым заядлым геймерам пришлось бы перезагружать свои высоконагруженные системы кнопкой reset после нескольких секунд работы игры.
Дело в том, что играя в тот же Battlefield, геймер в каждый новый момент времени видит различные объекты на экране монитора, например сейчас я стреляю во врага, а через долю секунды он уже падает убитым, создавая вокруг себя множество спецэффектов, таких как пыль, тени, и т.п.
Естественно, все это занимает какое-то место в оперативной памяти компьютера. Если не уничтожать неиспользуемые объекты, очень скоро они заполнят весь объем ресурсов ПК.
По этим причинам, в большинстве языков, в том числе и C/C++, имеется понятие указателя. Указатель — это переменная, хранящая в себе адрес ячейки оперативной памяти, например 0x100.
Мы можем обращаться, например к массиву данных через указатель, который будет содержать адрес начала диапазона ячеек памяти, хранящих этот массив.
После того, как этот массив станет не нужен для выполнения остальной части программы, мы просто освободим память по адресу этого указателя, и она вновь станет доступно для других переменных.
Ниже приведен конкретный пример обращения к переменным через указатель и напрямую.
Пример использования статических переменных
Пример использования динамических переменных
Во втором примере мы оперируем динамическими переменными посредством указателей. Рассмотрим общий синтаксис указателей в C++.
Логично предположить, что для разных типов данных выделяется разное количество памяти. Следует быть особенно осторожным при работе с памятью, потому что именно ошибки программы, вызванные утечкой памяти, являются одними из самых трудно находимых. На отладку программы в поисках одной ничтожной ошибки, может уйти час, день, неделя, в зависимости от упорности разработчика и объема кода.
В этих вещах очень часто возникают недопонимания, и кстати, не только у новичков. Многие из тех, кто начинал программировать с того же php, также часто испытывают подобную путаницу при работе с памятью.
Для того, чтобы освободить память, выделенную оператором new, используется оператор delete.
Пример освобождения памяти
При использовании оператора delete для указателя, знак * не используется.
Как стать программистом
Обучение основам программирования на C для чайников.
Страницы
Последние новости
YoungCoder теперь и на Stepikе. Записывайтесь: https://vk.cc/75rISy
Чтобы записаться на курс, необходимо зарегистрироваться на Степике: https://vk.cc/75rIC4
Это моя личная ссылка-приглашение на Stepik для вас. Регистрируясь по этой ссылке, записываясь на курсы и решая задачи, Вы помогаете автору данного сайта принять участие в конкурсе платформы Stepik! Подробности конкурса здесь: https://vk.cc/75rKuS
воскресенье, 28 июля 2013 г.
Занятие 13. Азы работы с файлами и потоками. Случайные числа.
Ну вот на этом все на сегодня. Практического задания к этому уроку не будет. Попрактикуйтесь сами, используя задания из прошлых двух занятий.
Если Вам понравился этот урок, расскажите о нем вашим друзьям. В этом Вам могут помочь кнопки основных социальных сетей, расположенные ниже. Вам остается всего лишь кликнуть по любой из них.
14 комментариев :
Объявив функцию freopen() дальнейшее использование scanf() приводит к тому, что элементы читаются из этого файла.
Как сделать так что бы в n-й раз данные считывались с файла, а в i-й с клавиатуры?
Частный случай: 1й раз считали с файла, во второй с клавиатуры, в третий с другого файла.
ну чтобы читать с другого файла, можно снова перенаправить поток, и делать так каждый раз. Как сбросить обратно к клавиатуре я что-то не знаю, быть может так и нельзя. Я еще поищу по этому поводу информацию.
Но для того, чтобы решить поставленную задачу есть другой способ. Здесь мы сразу весь поток перенаправили в файл, но мы могли действовать иначе. Мы могли использовать функции работы с файлами, и тогда могли бы выбирать откуда нам читать данные сейчас из файла или из стандартного потока.
В этом уроке лишь азы. =))) Разберем позже и работу с файлами
А почему при использовании функции rand() с такими же условиями выводит один и тот же набор чисел? Точно такие же, как у тебя в уроке. Я думал это генератор случайных чисел и он должен каждый раз новый выдавать, разве нет?
На самом деле это генератор псевдо случайных чисел, компьютеры пока что не обладают интеллектом, чтобы создавать что либо не заданное заранее в программе. Сдесь случайные числа задаются по определённому алгоритму от изначально заданного числа более подробно можно узнать в интернете.
Чуть ниже есть правильный ответ, на ваш вопрос. Думаю, об этом стоит упомянуть и в самом уроке. =)
#include
#include
int main(void) <
int arr[40],a,summ=0;
for(int i=0; i Ответить Удалить
ри повторном запуске программы, печатаются те же самые числа. Суть в том, что функция rand() один раз генерирует случайные числа, а при последующих запусках программы всего лишь отображает сгенерированные первый раз числа. Такая особенность функции rand() нужна для того, чтобы можно было правильно отладить разрабатываемую программу. При отладке программы, внеся какие-то изменения, необходимо удостовериться, что программа срабатывает правильно, а это возможно, если входные данные остались те же, то есть сгенерированные числа. Когда программа успешно отлажена, нужно, чтобы при каждом выполнении программы генерировались случайные числа. Для этого нужно воспользоваться функцией srand() из стандартной библиотеки С++. Функция srand() получив целый положительный аргумент типа unsigned или unsigned int (без знаковое целое) выполняет рандомизацию, таким образом, чтобы при каждом запуске программы функция srand() генерировала случайные числа.
Извиняюсь за спам. перечитал урок, все сам понял)))
int * array = new int[n]; что на самом деле делает эта функция?
Я смущен тем, как создать динамический определенный массив:
Я понятия не имею, что это делает. Я могу сказать, что он создает указатель с именем array, который указывает на новый объект / массив int? Кто-нибудь объяснит?
8 ответов
новая выделяет объем памяти, необходимый для хранения объектов/массив, который вы запрашиваете. В этом случае n чисел int.
указатель хранит адрес этого блока памяти.
но будьте осторожны, этот выделенный блок памяти не будут освобождены, пока вы не скажете Это так писать!—4—>
в противном случае, ваша программа будет утечка памяти не менее sizeof(int) * n байт (возможно больше, в зависимости от распределения стратегии реализации).
оператор в основном делает следующее:
Он выделяет пространство в куче, равное целочисленному массиву размером N, и возвращает указатель на него, который присваивается указателю типа int* под названием «array»
он выделяет столько места в соответствии со значением n, и указатель будет указывать на массив i.e 1-й элемент массива
в C/C++ указатели и массивы (почти) эквивалентны. int *a; a[0]; вернутся *a и a[1]; вернутся *(a + 1)
но массив не может изменить указатель, на который он указывает, в то время как указатель может.
new int[n] выделит некоторые пробелы для «массива»
это создает смарт-указатель на блок памяти, достаточно большой для n целые числа, которые автоматически удаляются, когда они выходят за рамки. Эта автоматическая очистка важна, потому что она позволяет избежать сценария, когда ваш код завершает работу рано и никогда не достигает вашего delete [] array; заявление.
другой (вероятно, предпочтительный) вариант будет использовать std::vector если вам нужен массив, способный динамически изменять размер. Это хорошо, когда вам нужно неизвестное количество пространства, но у него есть некоторые недостатки (непостоянное время для добавления/удаления элемента). Вы можете создать массив и добавить к нему элементы с помощью чего-то вроде:
общая форма new, применяемая к одномерным массивам, выглядит следующим образом:
Что означают эти функции?
Добавлено через 40 минут
ещё сразу вопрос, почему в этой программе нет функции memset() для обнуления памяти
Объяснить, что означают строки кода
float res = 0; res += f(a); res += f(b); res += f((a + b)/2); res /=3; объясните.
3)Зачем обнулять? Вы выделили диапазон памяти для массива и сразу же его заполнили.
Добавлено через 1 минуту
Это работает?
Adrian_One, всё работает, я просто спросил. Это язык Си.
Добавлено через 8 минут
Adrian_One, на счёт memset().. у нас в методичке просто сказано:
после использования функции malloc всегда проверять, успешно ли выделилась память! (проверять указатель на NULL).
После выделения память всегда нужно инициализировать! (memset())
вообще-то это одномерный массив, а двумерным он «становится» из-за магии указателей (a + i * m + j) и *(a + i * m + j) в циклах.
2 гетчара из-за кривизны функции scanf(), которая любит оставлять после себя символ ‘\n’ в потоке ввода.
я не это имел в виду, к двумерному массиву int ** a; вы можете обращаться стандартным способом: a[i][k], однако к массиву выделенному таким образом данная «магия» не применима, поскольку он является одномерным, т.е. int * a; и обращаться к нему получится только как a[i] без доступа ко «второму измерению» штатными средствами. Для чего используется пляска с бубном и указателями.
Вообще какая-то странная у вас тяга к исчерпывающим ответам, так и давали бы сами действительно исчерпывающий ответ, к которому никаких комментариев не нужно.