Основные операции с указателями




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

Пример:

int*x; int d; // не путать разадресацию со звёздочкой при объявлении указателя

int у = *х // у = 4;

В первой строке переменной-указателю х присваивается адрес, где хранится значение переменной d во второй строке переменной у присваивается разыменованное значение указателя х, т.е. значение 4. Если первую операцию написать без адреса, т.е. х = dх объявлен как int*x), то х будет указывать на ячейку памяти с адресом??:4 (?? - в зависимости от модели памяти) и значение переменной у будет равно значению,которое хранится по указанному адресу.

Операция определения адреса & возвращает адрес памяти своего операнда (переменной, константы, функции и т. д.). Формат получения адреса следующий:

<адрес> = & <переменная>;

Пример: int x, *y; y = &a; // указатель y содержит адрес х

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

 

Пример: int a, *x, *y; x =y;

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

 

Указатели и целые величины

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

char*a = "Slovo", c;

c = *(a+3); // c = 'v'

char*a, *b = "ABCDE";

a = b + 2; c = *(- - a;

char k = *a; int d = b-a)

Динамическое размещение указателей в памяти

 

Чтобы не вызвать конфликт в операционной системе или не нарушить работу приложения, нужно выделять место для указанного типа данных в допустимом пространстве памяти, которое называется «heap » или «куча».

Выделение (если есть возможность) памяти и присвоение её адреса указателю, по которому можно работать с описанным типом осуществляется библиотечной функцией malloc () или alloc(), (заголовочный файл <mem.h>), которую необходимо предварительно включить в программу директивой # include. Эти функции при последующих выделениях памяти предотвращают конфликты между указателями.

Формат использования данной функции:

<указатель> = (<тип_указателя>*) malloc (<размер_выделяемой_памяти_байт>);

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

Например, функция динамического распределения памяти может воспринимать размер (в байтах) объекта, для которого выделяется память, и возвращать указатель на тип void

double*dp;

d = (double*) malloc (sizeof(double)); // функция malloc () выделяет память

free dp: *dp = 22. / 7.0 // освобождение динамических выделений памяти.

При использовании функции обеспечивается преобразование возвращаемого значения из указателя на тип void в указатель на тип double.

 

Пример

/* ЗАНЯТИЕ N 8

Выполнил студент группы......... Петров Ю.В.

Применение указателей при работе с переменными

различных типов, изменение значений переменных по адресу

и по ссылке. Примеры операций с указателями */

 

#include <stdio.h>

#include <conio.h>

#include <string.h>

#include <alloc.h>

int a; //Объявление глобальной переменной типа int

int main(void)

{char c1,c2,buf[20]; //buf-указатель на тип char

char *pc;

char *pst="\"slovo\"";//Объявление указателей на тип char

int *pi= &a;

float *pf, f=26.6; //Объявление указателя на тип float

double *pd, d; //Объявление указателя на тип double

double &sd= d; //Объявление ccылки на тип double

void *pv; //Объявление указателя на тип void

char *pchar=(char *)malloc(20);//Выделение памяти в куче

clrscr(); // Объявление функции void *malloc(size_t size);

pc=&c1; pf=&f; pd=&d;

printf(" Ввод переменной c1 типа char: ");

scanf("%c",pc); //Функция ввода данных, & - операция взятия

//адреса отсутствует

printf(" Вывод переменной c1 типа char: ");

printf("%c\n",*pc);

fflush(stdin);

pc=&c2;

printf(" Ввод переменной c2 типа char: ");

scanf("%c",pc); //Функция ввода данных, & - операция взятия

//адреса отсутствует

printf(" Вывод переменной c2 типа char: ");

printf("%c\n",*pc);

printf("\n Ввод переменной (a) типа int: ");

scanf("%d",pi);

a+=5; ++*pi; //Изменение а = а+5+1

printf(" \t Вывод (a) после изменения а=а+5+1\n");

printf(" Формат вывода (int): +6d #6o #8x\n");

printf("\t\t |%+6d|%#6o|%#8x|\n ",a,*pi,*pi);

printf("\n Вывод исходной cтроки: %s\n",pst);

pc=pst;

printf(" Вывод cтроки в цикле:\n");

while(*pc!='\0') { printf(" %s",pc); pc++; }

printf("\n Ввод cтроки в массив: ");

scanf("%s",buf);

pv=buf; //Использование указателя (pv) на тип void

printf(" Вывод cтроки из массива: %s\n",(char *)pv); //pv -void

printf(" Ввод cтроки в динамическую память: ");

scanf("%s",pchar);

printf(" Вывод cтроки из динамической памяти: %s\n",pchar);

printf(" Ввод переменных типа float and double (через пробел):\n");

printf("\t\t ");

scanf("%f %lf",pf,pd);

pv=pf; //Использование указателя (pv) на тип void

*pf=*(float *)pv*10; //f*=10;

*pd=sd+*(float *)pv; //Использование ccылки (sd) на тип double

pv=pd; //d+=f;

printf("\t Вывод результатов расчета f*=10 d+=f\n");

printf(" Формат вывода (float): 10.6f 10.6e +10.6g\n");

printf("\t\t |%10.6f|%10.6e|%+10.6g|\n",f,*pf,*pf);

printf(" Формат вывода (double): 10.8lf 10.8e 10.8g\n");

printf("\t\t |%10.8lf|%10.8e|%+10.8g|\n ",*pd,*(double *)pv,sd);

getche();

return 0;

}

/* Ввод переменной c1 типа char: w

Вывод переменной c1 типа char: w

Ввод переменной c2 типа char: t

Вывод переменной c2 типа char: t

 

Ввод переменной (a) типа int: 40

Вывод (a) после изменения а=а+5+1

Формат вывода (int): +6d #6o #8x

| +46| 056| 0x2e|

 

Вывод исходной cтроки: "slovo"

Вывод cтроки в цикле:

"slovo" slovo" lovo" ovo" vo" o" "

Ввод cтроки в массив: unsigned

Вывод cтроки из массива: unsigned

Ввод cтроки в динамическую память: dinamo

Вывод cтроки из динамической памяти: dinamo

Ввод переменных типа float and double (через пробел):

1.5 20.4

Вывод результатов расчета *pf=*pf*10; *pd=*pd+f;

Формат вывода (float): 10.6f 10.6e +10.6g

| 15.000000|1.500000e+01| +15|

Формат вывода (double): 10.8lf 10.8e 10.8g

|35.40000000|3.54000000e+01| +35.4|

*/

Ход работы

1 Изучить теоретические сведения.

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

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

4 Набрать программу на компьютере и устранить ошибки.

5.Получить результат.

6 Оформить отчет и сделать выводы по работе.

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

 

Индивидуальное задание к лабораторной работе №8

Присвоить раз именованному указателю на тип Р1 значение арифметического выражения АВ включающего указатели на типы Р2 и Р3. Арифметическое выражение реализовать в виде функции возвращающей указатель на тип Р1. Вывести на экран значение указателя Р2 и значение на которое он ссылается. Индивидуальные задания взять из таблицы 8.1.

Таблица 8.1 - индивидуальные задания

Вариант Р1 АВ Р2 Р3
  long (1/sin((р2)2))р3 int float
  float (abs(p3))1/p2 long double
  double tan((p3)2)p2/3 int long
  float (ln(p2)p3)p2 char unsigned long int
  long double sin(abs(p3)p2) double long int
  long sin(p2)/tan(p3) int float
  unsigned long int (++p3)/(--p2) short int int
  long double ((1+(++p2))/p3)p2 long int float
  signed long int (sin(--p2)-(p3))p3 char int
  long int (1/sin(p2))p3 unsigned long int int
  double sin(p3)1/p2 double float
  double cos(p2/p3) int double
  int (--p2)+(++p3) unsigned int short int
  signed int (sin(p2)/tan(p3))p3 short int char
  long double ln(--p2)1/p3 float double
  double 1.2*(10-(--p3))+p3 double short int
  double tan((p3)2)p2/3 double float
  float (ln(p2)p3)p2 int double
  long double sin(abs(p3)p2) unsigned int short int
  long double ((1+(++p2))/p3)p2 double long int
  signed long int (sin(--p2)-(p3))p3 int float
  long int (1/sin(p2))p3 short int int
  long double sin(abs(p3)p2) char int
  long sin(p2)/tan(p3) unsigned long int int
  double sin(p3)1/p2 double float
  double cos(p2/p3) int double
  int (--p2)+(++p3) unsigned int short int
  long double ((1+(++p2))/p3)p2 short int char
  signed long int (sin(--p2)-(p3))p3 float double
  long int (1/sin(p2))p3 double short int

 

 



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2022-09-06 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: