Файл: Лабораторная работа 1 Изучение среды разработки программ 3 Лабораторная работа 2 Исследование базовых типов данных языка Си 18.doc

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 05.12.2023

Просмотров: 285

Скачиваний: 3

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

СОДЕРЖАНИЕ

Лабораторная работа № 1Изучение среды разработки программ

ОСНОВНЫЕ ТЕОРЕТИЧЕСКИЕ СВЕДЕНИЯ

ПРОГРАММА РАБОТЫ

Лабораторная работа № 2Исследование базовых типов данных языка Си

МЕТОДИЧЕСКИЕ РЕКОМЕНДАЦИИ

ЗАДАНИЕ НА ИССЛЕДОВАНИЕ

Лабораторная работа № 3Исследование операций языка Си Цель занятия: Совершенствование навыков объявления, инициализации переменных и ввода и вывода информации Совершенствование навыков разработки программ в среде программирования MS Visual C++ Исследование возможностей языка С++ для реализации арифметических, логических и поразрядных операций над данными Время на выполнение работы: 4 часаПрограмма исследований: Исследование арифметических операций Исследование логических операций Исследование поразрядных операций Подготовка к выполнению работы: Изучить рекомендованную литературу (структура программы на языке высокого уровня, алфавит и элементарные конструкции языка Си, переменные и константы, стандартные типы данных, выражения и операции в языке Си). Изучить материал настоящего руководства. Материалы для подготовки к занятию: Конспект лекций. [1] стр. 31-38. Содержание отчета: Цели исследования. Программа работы. Листинги программ. Результаты исследований. Выводы по каждому пункту и общий вывод. МЕТОДИЧЕСКИЕ РЕКОМЕНДАЦИИ Любое выражение языка состоит из операндов (переменных, констант и др.), соединенных знаками операций. Знак операции - это символ или группа символов, которые сообщают компилятору о необходимости выполнения определенных арифметических, логических или других действий. Операции выполняются в строгой последовательности. Величина, определяющая преимущественное право на выполнение той или иной операции, называется приоритетом. В таблице 3.1 перечислены различные операции языка Си. Их приоритеты для каждой группы одинаковы. Чем большим преимуществом пользуется соответствующая группа операций, тем выше она расположена в таблице. Приоритеты могут регулироваться с помощью круглых скобок. Таблица 3.1 – Операции языка Си Знак операции Назначение операции ( ) Вызов функции [ ] Выделение элемента массива . Выделение элемента записи -> Выделение элемента записи (тождественно(.)) ! Логическое отрицание Поразрядное отрицание - Изменение знака ++ Увеличение на единицу -- Уменьшение на единицу & Взятие адреса * Обращение по адресу (тип) Преобразование типа (т.е. (float) a) sizeof( ) Определение размера в байтах * Умножение / Деление % Определение остатка от деления + Сложение - Вычитание << Сдвиг влево >> Сдвиг вправо < Меньше, чем <= Меньше или равно > Больше, чем >= Больше или равно = = Равно != Не равно & Поразрядное логическое "И" ^ Поразрядное исключающее "ИЛИ" | Поразрядное логическое "ИЛИ" && Логическое "И" || Логическое "ИЛИ" ?: Условная (тернарная) операция = Присваивание +=, - =, *=, /=, %=, <<=,>>=, &=, |=, ^= Бинарные операции (например, а *= b(т.е. a = a * b) и т.д.) , Операция запятая Для исключения путаницы в понятиях "операция" и "оператор", необходимо отметить, что оператор - это наименьшая исполняемая единица программы. Различают операторы выражения, действие которых состоит в вычислении заданных выражений (например: a = sin(b)+c; j++;), операторы объявления, составные операторы, пустые операторы, операторы метки, цикла и т.д. Для обозначения конца оператора в языке С++ используется точка с запятой. Что касается составного оператора (или блока), представляющего собой набор логически связанных операторов, помещенных между открывающей ({) и закрывающей (}) фигурными скобками ("операторными скобками"), то за ним точка с запятой не ставится. Отметим, что блок отличается от составного оператора наличием определений в теле блока. Охарактеризуем основные операции языка С++. Сначала рассмотрим одну из них - операцию присваивания (=). Выражение вида х = у + z;присваивает переменной х значение суммы переменных у и z. Наличие « ; » в конце операции говорит о том, что записан оператор. На первый взгляд все просто. Но очень часто у начинающих программистов возникает путаница в понимании этого оператора. Это связано с тем, что с точки зрения математики следующие два выражения в общем-то эквивалентны:х = у + z;у + z = х;Но программирование – есть процесс записи на формализованном языке последовательности команд, которые необходимо выполнить для достижения конечного результата. Из этого аспекта и вытекает ключевая разница из этих, казалось бы, тождественных выражений.Для любого языка программирования операция присваивания « = » в обязательном порядке подразумевает следующий порядок ее выполнения. Справа от знака « = » задается источник присваивания (то, что присваивается), а слева – приемник (или то, чему присваивается источник): х = у + z; Приемник Источник Первым вычисляется результат источника, который затем присваивается приемнику, НО НЕ НАОБОРОТ! Именно поэтому выражение у + z = х не имеет смысла! Источником может быть любая последовательность операций. Приемником – только переменная.По этой же причине оператор у + z;тоже бессмыслен, так как результат операции никуда не сохранен! (За исключением использования механизма перегрузки операции в классах, который будет рассмотрен во втором семестре). Операцию "=" разрешается использовать многократно в одном выражении, например: x = y = z = 100;Различают унарные, бинарные итернарные операции. У первых из них один операнд, у вторых – два и у третьих - три. В языке Си выделяют три группы операций: арифметические операции; логические операции и операции отношения; операции с битами. 1. Арифметические операции задаются следующими символами (таблица 3.1): +, -, *, /, %, -, !, . Например: a = b + c;a = b - c;a = b * c;a = b / c;a = b % c; a = !b;a = -b;a = b;a = sizeof (b);Операции +, -, * интуитивно понятны и не нуждаются в объяснении.Операции увеличения и уменьшения на 1 (++ и --).Эти операции, называемые также инкрементом и декрементом, имеют две формы записи - префиксную, когда операция записывается перед операндом, и постфиксную. В префиксной форме сначала изменяется операнд, а затем его значение становится результирующим значением выражения, а в постфиксной значением выражения является исходное значение операнда, после чего он изменяется.Операция определения размера sizeof предназначена для вычисления размера объекта или типа в байтах, и имеет две формы:sizeof выражение или sizeof( тип )Операции отрицания (-, ! и ). Арифметическое отрицание (унарный минус-) изменяет знак операнда целого или вещественного типа на противоположный. Логическое отрицание(!) дает в результате значение 0, если операнд есть истина( не нуль), и значение 1, если операнд равен нулю. Операнд должен быть целого или вещественного типа, а может иметь также тип указатель. Поразрядное отрицание(), часто называемое побитовым, инвертирует каждый разряд в двоичном представлении целочисленного операнда.Деление (/) и остаток от деления(%). Операция деления применима к операндам арифметического типа. Если оба операнда целочисленные, результат операции округляется до целого числа, в противном случае тип результата определяется правилами преобразования. Операция остатка от деления применяется только к целочисленным операндам. Знак результата зависит от реализации.Бинарные операции +=, -=, *= и /= эквивалентны следующим: a += 3;a -= 3;a *= 3;a /= 3;  a = a + 3;a = a - 3;a = a * 3;a = a / 3; 2. Поразрядные операции задаются следующими символами (таблица 3.1): <<, >>, &, |, ^. Например:a = b << 3;a = b >> 2;a = b & c;a = b | c;a = b ^ c;Операции сдвига (<< и >>) применяются целочисленным операндам. Они сдвигают двоичное представление первого операнда влево или вправо на количество двоичных разрядов, заданное вторым операндом. При сдвиге влево (<<) освободившиеся разряды обнуляются. При сдвиге вправо (>)освободившиеся биты заполняются нулями, если первый операнд беззнакового типа, и знаковым разрядом в противном случае. Операции сдвига не учитывают переполнение и потерю значимости.Примеры: int i=10, j, k ; /* i = 0000 1010 */k = i<<2 ; /* k = 0010 1000 */j = k<<1 ; /* j = 0101 0000 */i = j>>4 ; /* i = 0000 0101 */Битовые операции (&, |, ^) применяются только к целочисленным операндам и работают с их двоичными представлениями. При выполнении операций операнды сопоставляются побитового (первый бит первого операнда с первым битом второго, второй бит первого операнда со вторым битом второго, и т д.).При поразрядной конъюнкции, или поразрядном И (операция обозначается &) бит результата равен 1 только тогда, когда соответствующие биты обоих операндов равны 1.При поразрядной дизъюнкции, или поразрядном ИЛИ (операция обозначается |) бит результата равен 1 тогда, когда соответствующие биты хотя бы одного из операндов равен 1.При поразрядном исключающем ИЛИ (операция обозначается ^) бит результата равен 1 только тогда, когда соответствующий бит только одного из операндов равен 1.Примеры: int i=6, j=5, k ; /* i = 0110, *//* j = 0101 *//* --------- */k = i&j ; /* k = 0100 */k = i|j ; /* k = 0111 */k = j^j ; /* k = 0011 */3. Логические операции и операции отношения задаются следующими символами (таблица 3.1): <, <=, >, >=, ==, !=, &&, ||.Логические операции (&&и ||). Операнды логических операций И (&&) и ИЛИ (||) могут иметь арифметический тип или быть указателями, при этом операнды в каждой операции могут быть различных типов. Преобразования типов не производятся, каждый операнд оценивается с токи зрения его эквивалентности нулю (операнд, равный нулю, рассматривается как false, не равный нулю - как true).Результатом логической операции является true или false. Результат операции логическое И имеет значение true только если оба операнда имеют значение true. Результат операции логическое ИЛИ имеет значение true, если хотя бы один из операндов имеет значение true. Логические операции выполняются слева направо. Если значение первого операнда достаточно, чтобы определить результат операции, второй операнд не вычисляется. Результаты логических операций могут быть представлены следующим образом:Таблица 3.2 – Логические операции языка Си x y x && y x || y 0 0 0 0 0 1 0 1 1 0 0 1 1 1 1 1 Операции отношения (<, <=, >, >=, = =, !=) сравнивают первый операнд со вторым. Операнды могут быть арифметического типа или указателями. Результатом операции является значение true или false (любое значение, не равное нулю, интерпретируется как true). Операции сравнения на равенство и неравенство имеют меньший приоритет, чем остальные операции сравнения. Результаты операций отношения могут быть представлены следующим образом:Таблица 3.3 – Операции отношения языка Си  x y x < y x <= y x > y x >= y x = = y x != y 0 0 false true false true true false 0 1 true true false false false true 1 0 false false true true false true 1 1 false true false true true false 1>2>1   2   3   4   5   6   7   8   9   ...   22

ЗАДАНИЕ НА ИССЛЕДОВАНИЕ Исследование арифметических операций для заданных исходных данных исследовать влияние типа данных на конечный результат для всех арифметических операций. Пример:typedef signed short int INT;int main(int argc, char* argv[]){INT a=12678, b=-19003, c;float x=a,y=b,z;char d=156,e=68,f;cout<<"\n------------------\nInteger: a="<c=a-b; cout<<"\n-: "<c=a*b; cout<<"\n*: "<c=a/b; cout<<"\n/: "<c=a%b; cout<<"\n%: "<c=-a; cout<<"\n-: "<c=!a; cout<<"\n!: "<c=a; cout<<"\n

Лабораторная работа № 4Применение управляющих инструкций языка для организации ветвлений в программе

ОСНОВНЫЕ ТЕОРЕТИЧЕСКИЕ СВЕДЕНИЯ

ПРОГРАММА РАБОТЫ

ЗАДАНИЕ ДЛЯ САМОСТОЯТЕЛЬНОЙ РАБОТЫ

Лабораторная работа № 5Исследование циклов

МЕТОДИЧЕСКИЕ РЕКОМЕНДАЦИИ

ЗАДАНИЕ НА ИССЛЕДОВАНИЕ

Лабораторная работа № 6Применение массивов и указателей для решения прикладных задач

ОСНОВНЫЕ ТЕОРЕТИЧЕСКИЕ СВЕДЕНИЯ

ПРОГРАММА РАБОТЫ

Лабораторная работа № 7Исследование массивов и указателей

МЕТОДИЧЕСКИЕ РЕКОМЕНДАЦИИ

ЗАДАНИЕ НА ИССЛЕДОВАНИЕ

Лабораторная работа № 8Применение функций работы со строками для решения прикладных задач

ОСНОВНЫЕ ТЕОРЕТИЧЕСКИЕ СВЕДЕНИЯ

ПРОГРАММА РАБОТЫ

МЕТОДИЧЕСКИЕ РЕКОМЕНДАЦИИ

ЗАДАНИЕ НА ИССЛЕДОВАНИЕ

Практическое занятие № 6Использование функций для работы с массивами

ОСНОВНЫЕ ТЕОРЕТИЧЕСКИЕ СВЕДЕНИЯ

ПРОГРАММА РАБОТЫ

Практическое занятие № 7Программирование рекурсивных алгоритмов

ОСНОВНЫЕ ТЕОРЕТИЧЕСКИЕ СВЕДЕНИЯ

ПРОГРАММА РАБОТЫ

Практическое занятие № 8Применение производных типов данных для решения прикладных задач

ОСНОВНЫЕ ТЕОРЕТИЧЕСКИЕ СВЕДЕНИЯ

ПРОГРАММА РАБОТЫ

Лабораторная работа № 5Исследование методов доступа к файлам данных

МЕТОДИЧЕСКИЕ РЕКОМЕНДАЦИИ

ЗАДАНИЕ НА ИССЛЕДОВАНИЕ

Лабораторная работа № 6Исследование связанных списков данных

МЕТОДИЧЕСКИЕ РЕКОМЕНДАЦИИ

ЗАДАНИЕ НА ИССЛЕДОВАНИЕ

ЛИТЕРАТУРА

A3[0][1][0] равен 2, элемент A3[3][0][1] равен 19 и т.д.

Если в списке инициализации в какой-то из размерностей не хватает данных, то все дальнейшие не перечисленные элементы считаются равными нулям.

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

Указатели, подобно любым другим переменным, перед своим использованием должны быть объявлены. Объявление указателя имеет вид:

type *ptr;

где type - один из предопределенных или определенных пользователем типов, а ptr - указатель. Например,

int *countPtr, count;

объявляет переменную countPtr типа int * (т.е. указатель на целое число) и переменную count целого типа. Символ * в объявлении относится только к countPtr. Каждая переменная, объявляемая как указатель, должна иметь перед собой знак звездочки (*). Если в приведенном примере желательно, чтобы и переменная count была указателем, надо записать:

int *countPtr, *count;

Символ * в этих записях обозначает операцию косвенной адресации.

Может быть объявлен и указатель на void:

void *Pv;

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

Pv = countPtr;

В Cи указатели используются очень широко. Указатели должны инициализироваться либо при своем объявлении, либо с помощью оператора присваивания. Указатель может получить в качестве начального значения 0, NULL или адрес. Указатель с начальным значением 0 или NULL ни на что не указывает. NULL - это символическая константа, определенная специально для цели показать, что данный указатель ни на что не указывает. Пример объявления указателя с его инициализацией:

int *countPtr = NULL;

Для присваивания указателю адреса некоторой переменной используется операция адресации &, которая возвращает адрес своего операнда. Например, если имеются объявления

int Step = 5;

int *ptr, Num
;

то оператор

ptr = &Step;

присваивает адрес переменной Step указателю ptr.

Операцию разыменования нельзя применять к указателю на void, поскольку для него неизвестно, какой размер памяти надо разыменовывать.

Для того, чтобы получить значение, на которое указывает указатель, используется операция *, обычно называемая операцией косвенной адресации или операцией разыменования. Она возвращает значение объекта, на который указывает ее операнд (т.е. указатель). Например, если продолжить приведенный выше пример, то оператор

Num = *ptr;

присвоит переменной Num значение 5, т.е. значение переменной Step, на которую указывает ptr.

Здесь необходимо обратить внимание на разночтение символа «. Если символ « стоит перед идентификатором переменной при ее объявлении, то смысл этой «звездочки» - сказать, что объявляется не обычная переменная, а переменная-указатель. Во всех остальных случаях символ « читается и воспринимается программой как «взятие значения по адресу», то есть является операцией косвенной адресации.


ПРОГРАММА РАБОТЫ


  1. Использование числовых массивов

  • набрать и отладить программу нахождения суммы элементов массива, стоящих в нечетных позициях:

#include

#include

int main(int argc, char* argv[])
{

srand(time(0)); // Оператор 0

const int N=10;

int Arr[N];

int sum=0; // Оператор 1

for (int i=0;i

{

Arr[i]= rand()%100; // Оператор 2

cout<

}

for (int i=1;iОператор 3

sum+=Arr[i]; // Оператор 4

cout<<"\nSumma="<

return 0;

}

  • объяснить назначение операторов 0-4;

  • набрать и отладить программу нахождения суммы элементов массива, кратных 3:

#include

#include

int main(int argc, char* argv[])
{

time_t t;

srand((unsigned)time(&t));

const int N=10;

int Arr[N];

int sum=0; // Оператор 1

for (int i=0;i

{

Arr[i]=rand()%50; // Оператор 2

cout<

}

for (int i=1;i

if (Arr[i]%3==0) sum+=Arr[i]; // Оператор 3

cout<<"\nSumma="<

return 0;

}

  • объяснить назначение операторов 1-3;

  • набрать и отладить программу нахождения наибольшего элемента массива из N целых чисел с выводом номеров наибольших элементов:

#include

#include

int main(int argc, char* argv[])
{

srand(time(0));

const int N=10;

int Arr[N];

int index[N]={0}; // Оператор 1

int max, k=0;

for (int i=0;i

{

Arr[i]=rand()%100-50; // Оператор 2

cout<

}

max=Arr[0]; // Оператор 3

for (int i=1;i

if (Arr[i]>=max) // Оператор 4

{

max=Arr[i];

index[k]=i+1; // Оператор 5

k++;

}

k=0;

cout<<"\nMax="<

cout<<"\nИндексы: ";

while(index[k]>0) // Оператор 6

{

cout<

k++;

}

cout<

return 0;

}

  • объяснить назначение операторов 1-6.

  • Использование указателей

    • набрать и отладить следующую программу:

    int main(int argc, char* argv[])

    {

    int a=7, b=2;

    int *ptr=NULL;

    cout<<"\na="<

    cout<<", b="<

    ptr=&a;

    cout<<"\nДействие: ptr=&a. Результат: ptr="

    <


    ptr=&b;

    cout<<"\nДействие: ptr=&b. Результат: ptr="

    <<ptr<<", *ptr="<<*ptr;

    *ptr=137;

    cout<<"\nДействие: *ptr=137. Результат: b="<<b;

    ptr++;

    *ptr=-105;

    cout<<"\nДействие: ptr++, *ptr=-105. Результат: ptr="

    <


    return 0;

    }

    • объяснить работу программы.


    Занятие 7
    1   ...   6   7   8   9   10   11   12   13   ...   22

    Лабораторная работа № 7
    Исследование массивов и указателей



    Цель занятия:

    • Совершенствование навыков разработки программ в среде программирования MS Visual C++

    • Совершенствование навыков в использовании циклов для работы с массивами

    • Совершенствование навыков в программировании с использованием указателей

    • Исследование взаимосвязи между массивами и указателями

    • Исследование способов создания динамических массивов


    Время на выполнение работы: 2 часа
    Программа исследований:

    1. Исследование взаимосвязи между массивами и указателями

    2. Исследование способов создания динамических массивов


    Подготовка к выполнению работы:

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

    2. Практически освоить порядок работы на ПЭВМ в интегрированной среде разработки MS Visual C++.


    Материалы для подготовки к занятию:


    1. Конспект лекций

    2. [1] стр. 51-63


    Содержание отчета:


    1. Цели исследования.

    2. Программу работы.

    3. Листинги программ

    4. Результаты исследований

    5. Выводы по каждому пункту и общий вывод.



    МЕТОДИЧЕСКИЕ РЕКОМЕНДАЦИИ



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

    int A[5]={-2,5,4,-17,3};

    Посмотрим, как этот массив разместится в оперативной памяти (рисунок 7.1).



    .

    .

    .




    A[4]










    0x0012FF90













    A[3]




    0x0012FF8C













    A[2]




    0x0012FF88













    A[1]




    0x0012FF84













    A[0]




    0x0012FF80










    .

    .

    .





    const int *A





    0х0012FF70













    .

    .

    .


    Рисунок 7.1 – Представление массива элементов в памяти ЭВМ
    Обратите внимание, что под хранение значения каждого элемента массива выделяется четыре ячейки памяти, что видно из чередования адресов ячеек памяти через четыре байта. Это связано с тем, что тип этого массива – int. Причем, под хранение адреса начала массива выделяется тоже четыре байта, так как все указатели для 32-разрядных процессоров 4-х байтные.

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

    int b[5] = {1,2,3,4,5}, *Pt;

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

    Это эквивалентно присваиванию адреса первого элемента массива следующим образом: Pt = &b[0];

    Теперь можно сослаться на элемент массива b[3] с помощью выражения *(Pt + 3).

    Указатели можно индексировать точно так же, как и массивы. Например, выражение Pt[3] ссылается на элемент массива b[3].

    Или, например, определение int a[5]; задает массив из пяти элементов а[0], a[1], a[2], a[3], a[4]. Если объект определен как

    int *у;

    то оператор

    у = &a[0];

    присваивает переменной у адрес элемента а[0]. Если переменная у указывает на очередной элемент массива а, то y+1 указывает на следующий элемент, причем здесь выполняется соответствующее масштабирование для приращения адреса с учетом длины объекта (для типа int – 4 байта, long - 4 байта, (double - 8 байт и т.д.).

    Так как само имя массива есть адрес его нулевого элемента, то оператор у = &a[0]; можно записать и в другом виде: у = а. Тогда элемент а[1] можно представить как *(а+1). С другой стороны, если у - указатель на массив a, то следующие две записи: a[i] и *(у+i) эквивалентны. Рассмотрим пример:

    int main(int argc, char* argv[])

    {

    int a[5]={-5,0,34,12,-17};

    cout<оператор 1

    cout<оператор 2

    cout<оператор 3

    cout<оператор 4

    cout<<endl;

    return 0;

    }

    Так, операторы 1 и 2 выведут одно и то же значение – адрес элемента массива с индексом 2. А операторы 3 и 4 – одно и то же значение 34.

    Между именем массива и соответствующим указателем есть одно важное различие. Указатель - это переменная и у = а или y++ - допустимые операции. Имя же массива - константа, поэтому конструкции вида a = y, a++ использовать нельзя, так как значение константы постоянно и не может быть изменено.

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

    С указателями может выполняться ограниченное количество арифметических операций. Указатель можно увеличивать (++), уменьшать (--), складывать с указателем целые числа (+ или +=), вычитать из него целые числа (- или -=) или вычитать один указатель из другого.

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

    Pt += 2;

    Pt будет указывать на третий элемент массива b. Истинное же значение указателя Pt изменится на число байтов, занимаемых одним элементом массива, умноженное на 2. Например, если каждый элемент массива b занимает 2 байта, то значение Pt (т.е. адрес в памяти, на который указывает Pt) увеличится на 4.

    Аналогичные правила действуют и при вычитании из указателя целого значения.

    Переменные указатели можно вычитать один из другого. Например, если Pt указывает на первый элемент массива b, а указатель Pt1 - на третий, то результат выражения Pt1 - Pt будет равен 2 - разности индексов элементов, на которые указывают эти указатели. И так будет, несмотря на то, что адреса, содержащиеся в этих указателях, различаются на 4 (если элемент массива занимает 2 байта).

    Арифметика указателей теряет всякий смысл, если она выполняется не над указателями на массив. Сравнение указателей операциями >, <, >=, <= также имеют смысл только для указателей на один и тот же массив. Однако, операции отношения == и != имеют смысл для любых указателей. При этом указатели равны, если они указывают на один и тот же адрес в памяти.

    Динамические массивы создают с использованием операции new, при этом необходимо указать тип и размерность, например:

    int a=10;

    int *ptr=new int [a];

    В этой строке создается переменная-указатель на int, в динамической памяти отводится непрерывная область, достаточная для размещения 10 элементов целого типа, и адрес ее начала записывается в указатель ptr. Динамические массивы нельзя при создании инициализировать, и они не обнуляются.

    Доступ к элементам динамического массива осуществляется точно так же, как к статическим, например, к элементу номер 5 можно обратиться как ptr[5] или *(ptr+5).

    Альтернативный способ создания динамического массива – использование функции malloc библиотеки Си:

    int a=10;

    int *ptr=(int*)malloc(a*sizeof(int));

    Операция преобразования типа, записанная перед обращением к функции malloc, требуется потому, что функция возвращает значение указателя типа void*.

    Память, зарезервированная под динамический массив с помощью new[], должна освобождаться оператором delete [], а память, выделенная функцией malloc – посредством функции free, например:

    delete [] ptr;

    free(ptr);

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


    1   ...   7   8   9   10   11   12   13   14   ...   22