Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
тп_лекции_2сем.docx
Скачиваний:
6
Добавлен:
18.04.2015
Размер:
59.18 Кб
Скачать

Указатели

- специальный тип данных предназначены для хранения адресов памяти. Не является самостоятельным типом данных, всегда связан с каким либо другим конкретным типом.

3 вида:

  1. Типизированные

  2. Бестивовые (абстрактные)

  3. Указатели на функции

Типизированные

Содержит адрес области памяти, в которой хранятся данные определенного типа.

Объявление: тип *имя [инициализатор]

Тип – тип переменной, на которую указатель будет ссылаться

*- символ организует указатель

Бестиповые

Для описания таких указателей в качестве базового используется тип void

Void * имя [инциализатор]

Указателю можно присвоить значение указателя на любой тип данных, а также сравнивать его с любыми указателями. Перед выполнением каких-либо действий с областью памяти, адрес который содержится в абстрактном указателе необходимо выполнить операцию преобразования типов.

Операция разыменования

*указатель

Позволяет обратиться к содержимому памяти, адрес которой храниться в указателе.

Получение адреса

& переменная

Возвращает адрес конкретной переменной. Этот адрес можно поместить в указатель соответствующего типа тем самым инициализируя этот указатель

Инициализация указателей

  1. Присвоение указателю уже существующего объекта

  2. Присвоению указателю значения другого уже инициализированного указателя

  3. Присвоение указателю адреса памяти в явном виде

  4. Присвоение указателю специального значения NULL

Выделение динамической памяти

Классы памяти:

  1. Статическая – выделяется на этапе компиляции для глобальных переменных и переменных описанных как static

  2. Память стека – выделяется для локальных переменных. При выходе из блока память автоматически освобождается.

  3. Динамическая – память выделяется и освобождается по запросу, допускается повторное выделение освобождения памяти.

Механизмы выделения и освобождения памяти:

Механизм языка С

  • Память выделяется с помощью функции malloc

Void *malloc (объем выделенной памяти)

  • Память освобождается с помощью функции free

Void free (void*)

! Значение указателя не изменяется после функции free

Механизмы С++

  • память выделяется с помощью операции new – возвращает указатель на выделенный участок памяти

new тип

  • освобождается с помощью delete

delete указатель

! Значение указателя не изменяется после выполнения delete

Арифметические операции над указателями:

Сложение с константой, вычитание, инкремент, декремент. Арифметические операции с абстрактными указателями недопустимы.

При выполнении операций учитывается длина базового типа, адресуемого указателями

  • если было описание int *p и выполняем операцию р++, то значение увеличится не на 1, а на size of (int)

  • добавление 1 к указателю добавит «квант памяти», т.е. количество байтов которые занимает значение адресуемого типа.

  • Разность между двумя указателями – разность их значений, деления на размер типа в байтах

  • Суммирование двух указателей не допускается

Константные указатели

- указатели значение которых не изменяется в ходе выполнения программы

указательный_тип: const имя инциализатор

изменить значение константного указателя нельзя, но можно изменить значение в памяти, адрес которой находиться в указателе.

Указатели на константу

- указатели содержащие адрес константы

сonst указательный_тип имя [инциализатор]

изменить значение такого указателя можно, в изменить значение памяти, адрес корой находиться в указатели нельзя.

Указатели и одномерные массивы

Объявлен массив m и указатель ps:

Short m[8];

Short *ps;

Идентификатор m будет восприниматься как указатель на первый элемент, значение которого нельзя изменить. С именем массива можно работать как с указателем на первый элемент:

ps=m;

cout<<m<<ps; // 0013FEDC 0013FEDC

применяя к идентификатору одномерного массива операцию [n] мы смещаемся на n-элементов относительно начала и разыменовываем полученный указатель на n элемент массива. Это можно сделать явно, используя адресную арифметику:

short а[8]={10,11,12,13,14,15,16,17};

cout<<a[3]; //13

cout<<*(a+3); // 13

Динамические массивы

- массив, если в процессе программы можно менять его размерность.

Особенности выделения памяти для массива:

  • Указатель объявляется на базовый тип массива

  • Размер массива указателя в квадратных скобках после идентификатора типа new

  • Допустим не константный размер массива

Для получения доступа к элементы массива, разыменовывать указатель не нужно. Операция индексации [] вычисляет адрес элемента массива и разыменовывает соответствующий указатель.

Квадратные скобки после delete, но размер массива не указывается.

int k=0; cin>>k; //4

short *pa=new short [k];

cout<<&pa; //0013FF5C

cout<<pa; //003B6188

for (int i=0; i<k; i++) pa[i]=i*i;

cout<<*pa; //0

cout<<pa[2]; //4

delete []pa;

Строки C++

Символьная константа – целое значение представленная как символ в одинаковых кавычках.

Значение символьной константы – целочисленное значение в наборе машинных символов.

Строка – последовательность символов, рассматриваемые как единое целое.

Строка может включать буквы цифры специальные символы и т.д.

Строковые литералы (строковые константы) записываются в двойных кавычках.

Способы представления строк символов:

  • В виде одномерного массива символов (строки завершаются нулевым байтом)

  • В виде объекта string

  • Другие способы в зависимости от реализации

Строки, завершающиеся нулевым байтом:

  • Описывается как одномерный массив, каждый элемент которого имеет тип char

  • Символы строки последовательно размещаются в элементах массива, начиная с нулевого

  • В элемент массива следующим за последним символом автоматически записывается элемент с кодом 0 «\0»

Описание строк завершающиеся нулевым байтом:

  • Строка описывается как обычный массив символов char

  • Размер массива должен быть на 1 больше, длины самой длинной строки, которую предполагается хранить в этом массиве

Основные отличия строк от самих массивов:

  • В процессе выполнения программы отслеживается текущая длина строки

  • Стока в целом может быть проинициализирована значением строкового литерала, а не только поэлементно символьным значением

  • При помещении идентификатора символьного массива в поток cout выводиться адрес массива, а его содержание от 0-10 элемента до последнего перед завершающим символом 10

Если запустить программу из примера 1 и ввести строку, состоящий из нескольких слов выводиться только первое слово. Это связано с тем, что ввод выполняется только до первого пробельного символа. Можно вывести эти слова отдельно в строковые переменные (пример 2) это не всегда удобно.

Если требуется ввести строку из нескольких слов в одну строковую переменную, используют функцию get line или get.

Метод get line считывает из входящего потока n-1 символов или меньше (если символ перевода строки встречается раньше) и записывает в строковую переменную.

Символ перевода строки так же считывается (удаляется) из входного потока, но не записывается в строковую переменную, вместо него помещается завершающий ноль.

Если в троке исходных данных более n-1 символов следующий ввод будет начинаться с той же строки, начиная с первого несчитанного символа.

Метод get работает аналогично, но оставляет в потоке символ перевода строки.

В строковую переменную добавляется завершающий 0. Нельзя обратиться к get 2 раза подряд не удалив \n из входного потока. Чтобы удалить \n из потока, необходимо вызвать get без параметров cin.get()

Операции со строками

Поиск подстроки в строке

Char strstr (char s1, const char s2);

Выполняет поиск подстроки s2 в строке s1 возвращает указатель на строку s2 если та присутствует в s1 и 0 в противном случае.

Копирование строки

Char strcpy (char s1, const char s2);

Копирует строку s2 в массив символов s1, возвращает значение s1.

Char strncpy (char s1, const char s2, size_t n);

Копирует не более n-символов из s2 в s1. Возвращает значение s1.

Добавление строки

Char strcat (char s1, const char s2);

Добавляет s2 в строку s1 первый символ s2 записывается поверх завершающего символа s1, возвращает строку s1.

Char strncat (char s1, const char s2, size_t n);

Добавляет не более n-символов строки s2 в строку s1 первый символ из s2 записывается поверх завершающего символа строки s1, возвращает значение s1.

Сравнение

int strcmp (const char s1, const char s2);

Сравнивает строки s1и s2, функция возвращает 0, если s1=s2 , меньше нуля, если s1<s2, больше нуля, если s1>s2.

int strcmp (const char s1, const char s2, size_t n);

сравнивает до n-символов строки s1 и s2 возвращает ноль, <0, >0, если s1 соответственно равна меньше или больше s2.

Выделение лексем из строки

char strtok (char s1, const char s2);

разбивает строку на лексемы – логические куски, такие как слова в строке текста разделенные символами содержащиеся в s2. Первый вызов содержит в качестве первого аргумента s1, а последующие вызовы для продолжения обработки той же строки содержит в качестве первого аргумента NULL. При каждом вызове возвращает указатель на текущею лексему, если при вызове функции больше нет возвращается NULL.

Длина строки

char strlen (const char s);

возвращает количество символов предшествующих завершающему нулевому символу.

char strchr (char s, int c);

возвращает указатель на первое вхождение символа c в строку s. Если символ отсутствует возвращает NULL.

Простые типы, определяемые пользователем

Переименование типов

Typedef тип новое_имя [размерность]

Для того чтобы сделает программу более ясной, можно встроенному типу задать новое имя с помощью typedef

Typedef unsingned int UNIT;

Typedef char Msd [100];

Введенные таким образом имена можно использовать как имена стандартных типов

UNIT i,j //две переменные типа undigned int

Msd str[10] //массив из 10 строк по 100 символов

Замечание: рекомендуется писать имена задаваемые typedef писать заглавными буками, чобы подчеркнуть что эти имена является синонимами других имен типа.

Перечисление (enum)

Чтобы определить несколько констант имеющие фиксированное название удобно использовать перечисляемым типом данных все возможные значения которого задается списком целочисленных констант:

Enum [имя_типа] {список констант }

Enum - служебное слово

[имя типа] – необязательный параметр

{список контакт} разделенные запятыми последовательность идентификаторов или именованных констант вида: имя_констант = значение_констант.

Имя типа задается, в случае если про проге нужно определить переменные этого типа. Константы должны быть целочисленными и инициализироваться обычным образом. При осуществлении инциализатора первая константа обнуляется, а каждой следующей присваивается значение на единицу больше предыдущей. Если в списке нет ни одного элемента со знаком равно то значение константы начинается с нуля и увеличивается на единицу. Имена перечисляемых констант должны быть уникальными, а значения могут совпадать. Для переменных перечисляемого типа можно определить собственные операции.

Структуры

- объединение в единое целое множество поименнованых элементов данных. В соответствии со списком компоненты могут иметь любой тип данных допустимых в языке.

Синтаксис:

Struct [имя типа]{

Mun_n элемент_n;}[список описателей];

Элементы структуры могут иметь любой тип кроме типа этой же структуры но могут быть указаны на него. Если отсутствует имя типа, должен быть указан список описателей идентификатора. В этом случае описание структур служит определителем элементов этого списка.

Еще одну возможность ввести структурный тип дает слово typedef позволяет ввести собственное определение для любого значения.

Структурный тип которому назначают имя с помощью typedef может иметь второе имя вводимое стандартным образом после struct.

Определение структур

при определении структурного типа его компонентам не выделяется память и их нельзя проинициализировать.

[struct] имя_струк_типа имя_переменной;

Безымянный тип структуры

Выделение памяти для структур:

Sizeof (имя структуры)

Sizeof (имя струк. типа)

Инициализация структур

Для инициализации можно значение элементов перечислить в фигурных скобках порядки их описания.

При инициализации массивов структур следует заключать в фигурные скобки каждый элемент массива. Для переменных одного и того же структурного типа определена операция присваивания, при этом происходит поэлементное копирование. Размер структуры не обязательно равен сумме размеров ее элементов, поскольку они необязательно располагаются в соседних ячейках.

Доступ к элементам структур

Обеспечивается с помощью операции уточнения имени «.»

Конструкция: имя_структуры_типа_переменной . имя_поля

Операция точка – операция доступа к элементам структуры самый высокий ранг на ряду со скобками левый операнд должен иметь структурный тип, а правый – именем поля этой структуры. Тп результата точка- тип поля структуры.

Если обращение к полю осущ. через указатель на структуру типа, то точка заменяется на ->

Объединения в с++

можно рассматривать как структуры, все элементы которой имеют нулевое смещение от начала. При таком размещение разные элементы занимают в памяти один и тот же участок. Тем самым объединение обеспечивает возможность доступа к одному и тому же участку памяти с помощью переменных разного типа.

Union [имя типа]{оперделение элементов}

Отличие структуры от объединения состоит в том, что записать информацию в объединении можно с помощью одного из элементов а выбрать данные их того же участка памяти с помощью ого элемента того же объединения.

Объединение – конкретный объект которому выделено место в памяти, размеры участка памяти выделяемого для объединения должны быть достаточны для размещения самого большого элемента объединения.

Битовые поля

Особый вид полей структуры. Исп. Для плотной упаковки данных. При описании битового поля после имени через «:» указывается длинна поля в битах может быть любого битового поля можно использовать как обычные поля. Битовые поля могут быть и элементами объединения.

Модульное программирование

С помощью С++ программа может быть разбита на более обозримые части с помощью функций. Использование функций является первым шагом к повышению степени абстракции программы и ведет к упрощению ее структуры. Разделение программы на функции позволяет также избежать избыточности кода, польку функция записывается 1 раз, а вызывать ее на выполнение можно неоднократно из разных точек программы. Процесс откладки программы содержащая функцию легче структурировать, часто используемую функцию можно помещать в библиотеки. Модуль содержит данные и функции их обработки. Другим модулям не желательно иметь средство обработки этих данных. Чтобы использовать модуль нужно знать интерфейс, а не детали реализации. Чем более независимы модули тем легче отлаживать программу. Интерфейсом модуля является: заголовки всех функций и описание доступных из вне типов переменных и констант.

Функции

- именованная последовательность описаний и операторов, выполняемых какое-либо действие. Может принимать параметры и возвращать значения.

Функция начинает выполняться во время ее вызова. Любая функция должна быть объявлена и определена. Объявлений может быть несколько, определение только одно. Объявление должно находится в тексте раньше ее вызова для того чтобы компилятор мог осуществить проверку правильности вызова.

Объявление функции (прототип), заголовок, сигнатура - задает ее имя, тип возвращаемого значения и список предаваемых параметров.

Определение функции содержит кроме объявления, тело, представленная собой последовательностью описаний операторов в {}.

Синтаксис: [класс]тип имя_ф([список-праметров]){тело_ф}

С помощью необязательно параметра класс можно задать область видимости функции: extern(глобальная видимость во всех модулях программы по умолчанию), static (видимость в пределах модуля в котором определена функция)

Тип возвращаемого функцией значения может быть любым кроме массива и функции, но может быть указателем на массив или функцию. Если функция не должна возвращать значение указательный тип void.

Список параметров – определяет величины, которые требуется предать в функцию при ее вызове, элементы списка параметры разделяются запятыми. Для каждого параметра указывается его тип и имя. В объявлении функции имена можно опускать но типы должны присутствовать.

Тело функции ограничивается {} размещается за заголовками (в теле могут быть разные действия).

В определении в объявлении функции и при вызове одной и той же функции порядок следования параметров должен совпадать.

Вызов функции

Параметры, которые используются при объявлении функции – формальные.

Параметры, которые используются при вызове функции – фактические.

Соответствие между этими параметрами должно устанавливаться по их типам. При несовпадении типов компилятор принимает меры к устранению этих несовпадений путем приведения типов. При этом проверяется, доступны или нет такие преобразования. Кроме того компилятор всегда учитывает тип возвращаемого функцией значения.

Функции inline

Если функция сразу объявляется и определяется по умолчанию она рассматривается как встроенная, т.е. компилятор каждый раз при вызове такой функции помещает ее код в каждую точку вызова.

Можно определить функцию как строенную с помощью модификатора inline, который становиться перед типом функции. Эта возможность применяется для кротких функций, чтобы снизить накладные расходы на вызов.

Статические локальные переменные

Все величины, описанные внутри функции, а также ее параметры, являются локальными. Областью их действия является функция. При вызове функции, как и при входе в любой блок, в стеке выделяется память под локальные автоматические переменные. Кроме того, в стеке сохраняется содержимое регистров процессора на момент, предшествующий вызову функции, и адрес возврата из функции для того чтобы при выходе из нее можно было продолжить выполнение вызывающей функции.

При выходе из функции соответствующий участок стека освобождается, поэтому значения локальных переменных между вызовами одной и той же функции не сохраняются. Если этого требуется избежать, при объявлении локальных переменных используется модификатор static.

Статическая переменная п размещается в сегменте данных и инициализируется один раз при первом выполнении оператора, содержащего ее определение. Автоматическая переменная m инициализируется при каждом входе в функцию. Автоматическая переменная р инициализируется при каждом входе в блок цикла.

Глобальные переменные

Глобальные переменные видны во всех функциях, где не описаны локальные переменные с теми же именами.

Возвращаемые значения

Механизм возвращает значение из функции, реализуется с помощью – return.

Функция может содержать несколько операторов return. Выражение указанное после return не явно преобразуется к типу возвращаемого значение и передается в точку вызова. Если тип возвращаемого значения отличен от void то оператор вызова функции можно использовать в выражении. Если функция описана как void то она ничего не возвращает и не может участвовать в выражении.

Параметры функции

При вызове функции в первую очередь вычисляются выражения, стоящие на месте аргументов; затем в стеке выделяется память под формальные параметры функции в соответствии с их типом, и каждому из них присваивается значение соответствующего аргумента. При этом проверяется соответствие типов и при необходимости выполняются их преобразования.

Способы передачи параметров

Существует два способа передачи параметров в функцию: по значению и по адресу. При передаче по значению в стек заносятся копии значений аргументов, и операторы функции работают с этими копиями. Доступа к исходным значениям параметров у функции нет, а, следовательно, нет и возможности их изменить. Передача параметров по значению предусматривает момент:

  1. Компилятор выделяет спеицальную память для формальных параметров. Под float память выделяет как для double. Для char, short int как для int. Если аарметром являеться массив, то формируеться указатель на начало массива и он служит для представления массива параметров в теле функции

  2. Вычисления значения выражений используемых в качестве фактический параметров

  3. Значения фактических параметров заноситься память выделения формальных параметров.

  4. В стеке функция выполняется необходимая обработка информации и результат доставляется в точку вызова.

  5. Функция не оказывает ни какого влияния на фактические параметры.

  6. После выхода из функции память, которая выделилась под фактические параметры, освобождается.