Что такое findslide.org?

FindSlide.org - это сайт презентаций, докладов, шаблонов в формате PowerPoint.


Для правообладателей

Обратная связь

Email: Нажмите что бы посмотреть 

Яндекс.Метрика

Презентация на тему Указатели

Содержание

Зачем нужны указатели Существует три причины, по которым невозможно написать хорошую программу без использования указателей:указатели позволяют функциям изменять свои аргументыс помощью указателей осуществляется динамическое распределение памяти;указатели повышают эффективность многих процедур.Кроме того, использование указателей при обращении к
Указатели Зачем нужны указатели Существует три причины, по которым невозможно написать хорошую программу Что такое указательУказатель (pointer) – переменная, в которой хранится адрес другого объекта. Объявление указателяПеременная, содержащая адрес ячейки памяти, должна быть объявлена как указатель.Объявление указателя Операторы для работы с указателямиОператор m = &count;присваивает переменной m адрес переменной Инициализировать указатель можноиспользуя адрес уже объявленной переменной с помощью оператора взятия адреса Пример#include Присваивание указателейУказатель можно использовать в правой части оператора присваивания для присваивания его Преобразование типа указателяУказатель можно преобразовать к другому типуЭти преобразования бывают двух видов: В отличие от void *, преобразования всех остальных типов указателей должны быть Однако следует учитывать, что преобразование одного типа указателя к другому может вызвать Адресная арифметикаВ языке С допустимы только две арифметические операции над указателями: суммированиевычитаниеПредположим, Применительно к указателям на char, операций адресной арифметики выполняются как обычные арифметические К указателям можно добавлять целые числа или вычитать из них целые числа. Сравнение указателейСтандартом С допускается сравнение двух указателей. Например, если объявлены два указателя Указатели и массивы Доступ к элементам массива с помощью адресной арифметикиРассмотрим следующий фрагмент программы: char Обращение к элементам массиваВ языке С существуют два метода обращения к элементу Пример работы с массивами через указатели#include Индексация указателей на многомерные массивыНапример, если а – это указатель на двухмерный Массивы указателейКак и обычные переменные, указатели могут быть собраны в массив. В Указатели и строки Указатели и строкиБольшинство операций языка Си, имеющих дело со строками, работают с Массив и указатель: различияВозможны два способа объявления массива:static char heart[ ]= Но операцию увеличения можно использовать только с указателем:while ((*head) != '\0')	/* останов Предположим, мы хотим изменить head на heart. Можно так:head=heart; /* теперь head Вот каким путем можно изменить обращение к head и проникнуть в сам Массивы указателей часто используются при работе со строкамиНапример, можно написать функцию, выводящую
Слайды презентации

Слайд 2 Зачем нужны указатели
Существует три причины, по которым невозможно

Зачем нужны указатели Существует три причины, по которым невозможно написать хорошую

написать хорошую программу без использования указателей:
указатели позволяют функциям изменять

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


Слайд 3 Что такое указатель
Указатель (pointer) – переменная, в которой

Что такое указательУказатель (pointer) – переменная, в которой хранится адрес другого

хранится адрес другого объекта. Обычно – это адрес другой

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



Слайд 4 Объявление указателя
Переменная, содержащая адрес ячейки памяти, должна быть

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

объявлена как указатель.
Объявление указателя состоит из имени базового типа,

символа * и имени переменной.
В общем виде объявление указателя записывается в виде:
тип_указателя *имя_указателя;
Базовый тип указателя определяется типом переменной, на которую он может ссылаться. Им может быть любой допустимый тип.
Например,
int *pointer, *mas[10];
float *pointer;


Слайд 5 Операторы для работы с указателями
Оператор
m = &count;
присваивает

Операторы для работы с указателямиОператор m = &count;присваивает переменной m адрес

переменной m адрес переменной count. Этот адрес относится к

ячейке памяти, которую занимает переменная count. Если переменная занимает несколько ячеек памяти, ее адресом считается адрес первого байта.
Если m содержит адрес переменной count, то оператор
q = *m;
присваивает переменной q значение переменной count.

Предположим, переменная count хранится в ячейке памяти под номером 0012FF64, а ее значение равно 25. Тогда переменной m будет присвоено значение 0012FF64.


Слайд 6 Инициализировать указатель можно
используя адрес уже объявленной переменной с

Инициализировать указатель можноиспользуя адрес уже объявленной переменной с помощью оператора взятия

помощью оператора взятия адреса &
выделяя под него память функцией

malloc()


Слайд 7 Пример
#include "stdafx.h"
#include "conio.h"
void main() {
int someVariable = 4;

Пример#include

//объявляем и инициализируем переменную someVariable
int *pointer; //объявляем указатель
pointer =

&someVariable; //инициализируем его адресом переменной someVariable
*pointer=*pointer+1; // изменяем значение, находящееся по адресу, на который ссылается указатель pointer
printf("Текущее значение переменной someVariable = %d\n", someVariable);
printf("Текущее значение переменной *pointer = %d", *pointer);
getch();
}
Выведет строки:
Текущее значение переменной someVariable = 5
Текущее значение переменной*pointer = 5

Слайд 8 Присваивание указателей
Указатель можно использовать в правой части оператора

Присваивание указателейУказатель можно использовать в правой части оператора присваивания для присваивания

присваивания для присваивания его значения другому указателю. Если оба

указателя имеют один и тот же тип, то выполняется простое присваивание, без преобразования типа. В следующем примере
#include
int main(void)
{
int x = 99; int *p1, *p2;
p1 = &x; p2 = p1;
printf("Значение по адресу p1 и p2: %d %d\n", *p1, *p2); /* печать значение x дважды */
printf("Значение указателей p1 и p2: %p %p", p1, p2); /* печать адреса x дважды */
return 0;
}
после присваивания
p1 = &x;
p2 = p1;
оба указателя (p1 и р2) ссылаются на х. То есть, оба указателя ссылаются на один и тот же объект. Программа выводит на экран следующее:
Значения по адресу p1 и р2 : 99 99
Значения указателей p1 и р2: 0063FDF0 0063FDF0


Слайд 9 Преобразование типа указателя
Указатель можно преобразовать к другому типу
Эти

Преобразование типа указателяУказатель можно преобразовать к другому типуЭти преобразования бывают двух

преобразования бывают двух видов:
с использованием указателя типа void

*
без его использования.
В языке С допускается присваивание указателя типа void * указателю любого другого типа (и наоборот) без явного преобразования типа указателя
Тип указателя void * используется, если тип объекта неизвестен. Например, использование типа void * в качестве параметра функции позволяет передавать в функцию указатель на объект любого типа, при этом сообщение об ошибке не генерируется. Также он полезен для ссылки на произвольный участок памяти, независимо от размещенных там объектов. Например, функция размещения malloc()возвращает значение типа void *, что позволяет использовать ее для размещения в памяти объектов любого типа.


Слайд 10 В отличие от void *, преобразования всех остальных

В отличие от void *, преобразования всех остальных типов указателей должны

типов указателей должны быть всегда явными
Т.е должна быть указана

операция приведения типов
(тип *)
В языке C++ требуется явно указывать преобразование типа указателей, в том числе указателей типа void *.

Слайд 11 Однако следует учитывать, что преобразование одного типа указателя

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

к другому может вызвать непредсказуемое поведение программы.
#include
int main(void)
{

double x = 100.1, y;
int *p;
/* В следующем операторе указателю на целое p
присваивается значение, ссылающееся на double. */
p = (int *) &x;
/* Следующий оператор работает не так, как ожидается. */
y = *p; /* attempt to assign y the value x through p */
/* Следующий оператор не выведет число 100.1. */
printf("Значение x равно: %f (Это не так!)", y);
return 0;
}


Слайд 12 Адресная арифметика
В языке С допустимы только две арифметические

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

операции над указателями:
суммирование
вычитание
Предположим, текущее значение указателя p1 типа

int * равно 2000.
Предположим также, что переменная типа int занимает в памяти 2 байта.
Тогда после операции увеличения
p1++;
указатель p1 принимает значение 2002, а не 2001. То есть, при увеличении на 1 указатель p1 будет ссылаться на следующее целое число. Это же справедливо и для операции уменьшения. Например, если p1 равно 2000, то после выполнения оператора
p1--;
значение p1 будет равно 1998.
Операции адресной арифметики подчиняются следующим правилам. После выполнения операции увеличения над указателем, данный указатель будет ссылаться на следующий объект своего базового типа. После выполнения операции уменьшения — на предыдущий объект

Слайд 13 Применительно к указателям на char, операций адресной арифметики

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

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

char всегда равна 1. Для всех указателей адрес увеличивается или уменьшается на величину, равную размеру объекта того типа, на который они указывают. Поэтому указатель всегда ссылается на объект с типом, тождественным базовому типу указателя. На рисунке приведен пример размещения в памяти переменных char (слева) и int (справа) (предполагается, что длина целочисленной переменной равна 2 байтам).

Слайд 14 К указателям можно добавлять целые числа или вычитать

К указателям можно добавлять целые числа или вычитать из них целые

из них целые числа. Выполнение оператора
p1 = p1

+ 12;
"передвигает" указатель p1 на 12 объектов в сторону увеличения адресов.
Кроме суммирования и вычитания указателя и целого, разрешена еще только одна операция адресной арифметики: можно вычитать два указателя. Благодаря этому можно определить количество объектов, расположенных между адресами, на которые указывают данные два указателя; правда, при этом считается, что тип объектов совпадает с базовым типом указателей. Все остальные арифметические операции запрещены.

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

Сравнение указателейСтандартом С допускается сравнение двух указателей. Например, если объявлены два

если объявлены два указателя р и q, то следующий

оператор является правильным:
if(p < q) printf("p ссылается на меньший адрес, чем q\n");
Однако, сравнение указателей может оказаться полезным, только тогда, когда два указателя ссылаются на общий объект, например, на массив.

Слайд 16 Указатели и массивы

Указатели и массивы

Слайд 17 Доступ к элементам массива с помощью адресной арифметики
Рассмотрим

Доступ к элементам массива с помощью адресной арифметикиРассмотрим следующий фрагмент программы:

следующий фрагмент программы:
char str[80], *p1;
p1 = str;
Имя массива

без индекса возвращает адрес первого элемента массива. Поэтому здесь p1 указывает на первый элемент массива str. Обратиться к пятому элементу массива str можно с помощью любого из двух выражений:
str[4]
или
* (p1+4)


Слайд 18 Обращение к элементам массива
В языке С существуют два

Обращение к элементам массиваВ языке С существуют два метода обращения к

метода обращения к элементу массива:
адресная арифметика
индексация массива
Стандартная запись

массивов с индексами наглядна и удобна в использовании, однако с помощью адресной арифметики иногда удается сократить время доступа к элементам массива. Поэтому адресная арифметика часто используется в программах, где существенную роль играет быстродействие.
/* Индексация указателя s как массива. */
void putstr(char *s) {
register int t;
for(t=0; s[t]; ++t) putchar(s[t]);
}
/* Использование адресной арифметики. */
void putstr(char *s) {
while(*s) putchar(*s++);
}

Слайд 19 Пример работы с массивами через указатели
#include "stdafx.h"
#include
#include

Пример работы с массивами через указатели#include


#define SIZE 10
 int main(void) {
int mass[SIZE], *p, *first,*max; first=mass;


for (p=mass; pp=mass; max=first;
while (p if (*p>*max) max=p;
p++;
}
printf("max = %d", *max);
 for (p=first; pprintf("%d ", *p);
 getch();
return 0;
}

Слайд 20 Индексация указателей на многомерные массивы
Например, если а –

Индексация указателей на многомерные массивыНапример, если а – это указатель на

это указатель на двухмерный массив целых размерностью 10×10, то

следующие два выражения эквивалентны:
a == &a[0][0]
Более того, к элементу (0,4) можно обратиться двумя способами:
либо указав индексы массива: а[0][4],
либо с помощью указателя: *((int*)а+4).
Аналогично для элемента (1,2): а[1][2] или *((int*)а+12).
В общем виде для двухмерного массива справедлива следующая формула:
a[j][k] эквивалентно *((базовый_тип*)а+(j*кол-во_столбцов)+k)
Правила адресной арифметики требуют явного преобразования указателя на массив в указатель на базовый тип


Слайд 21 Массивы указателей
Как и обычные переменные, указатели могут быть

Массивы указателейКак и обычные переменные, указатели могут быть собраны в массив.

собраны в массив. В следующем операторе объявлен массив из

10 указателей на объекты типа int:
int *x[10];
Для присвоения, например, адреса переменной var третьему элементу массива указателей, необходимо написать:
x[2] = &var;
В результате этой операции, следующее выражение принимает то же значение, что и var:
*x[2]
Для передачи массива указателей в функцию используется тот же метод, что и для любого другого массива: имя массива без индекса записывается как формальный параметр функции.
Например, следующая функция может принять массив x в качестве аргумента:
void display_array(int *q[])
{
int t;
for(t=0; t<10; t++)
printf("%d ", *q[t]);
}
Необходимо помнить, что q – это не указатель на целые, а указатель на массив указателей на целые.

Слайд 22 Указатели и строки

Указатели и строки

Слайд 23 Указатели и строки
Большинство операций языка Си, имеющих дело

Указатели и строкиБольшинство операций языка Си, имеющих дело со строками, работают

со строками, работают с указателями. Рассмотрим, например, приведенную ниже

бесполезную, но поучительную программу:
/* Указатели и строки */
#define PX(X) printf("X = %s; значение = %u; &X = %u\n",X,X,&X)
main( )
{
static char *mesg = "Сообщение";
static char *copy;
copy = mesg;
printf("%s\n",copy);
PX(mesg);
PX(copy);
}

Слайд 24 Массив и указатель: различия
Возможны два способа объявления массива:
static

Массив и указатель: различияВозможны два способа объявления массива:static char heart[ ]=

char heart[ ]="Я люблю язык Cи!";
char *head = "Я

люблю язык Pascal!";
Основное отличие состоит в том, что указатель heart является константой, в то время как указатель head - переменной. Посмотрим, что на самом деле дает эта разница.
Во-первых, и в том и в другом случае можно использовать операцию сложения с указателем:
for(i=0;i<7;i++)
putchar(* (heart+i));
putchar('\n');
for(i=0;i<7;i++)
putchar(* (head+i));
putchar('\n');
В результате получаем:
Я люблю
Я люблю


Слайд 25 Но операцию увеличения можно использовать только с указателем:
while

Но операцию увеличения можно использовать только с указателем:while ((*head) != '\0')	/*

((*head) != '\0') /* останов в конце строки */
putchar(*(head++)); /* печать

символа и перемещение указателя */
В результате получаем:
Я люблю язык Pascal!


Слайд 26 Предположим, мы хотим изменить head на heart. Можно

Предположим, мы хотим изменить head на heart. Можно так:head=heart; /* теперь

так:
head=heart; /* теперь head указывает на массив heart */
но

теперь можно и так
heart = head; /* запрещенная конструкция */
Ситуация аналогична x = 5 или 5 = x. Левая часть оператора присваивания должна быть именем переменной. В данном случае head = heart, не уничтожит строку про язык Cи, а только изменит адрес, записанный в head.


Слайд 27 Вот каким путем можно изменить обращение к head

Вот каким путем можно изменить обращение к head и проникнуть в

и проникнуть в сам массив:
heart[13] = 'C';
или
*(heart+8)='C';
Обратите внимание, переменными

являются элементы массива, но не имя!


  • Имя файла: ukazateli.pptx
  • Количество просмотров: 107
  • Количество скачиваний: 0