Указатели на объекты

В общем случае синтаксис определения указателя на объект:

Тип*Описатель;

При определении указателя специфицируется имя указателя-переменной (в дальнейшем указатель) и тип объекта, на который он ссылается.

Тип задает тип объекта, адрес которого будет содержать определяемая переменная и может соответствовать базовому, пустому (свободному, то есть типу void ), перечислению, структурному типу и типу объединения (будут рассмотрены позже). Реально указатель на void ни на что не указывает, но обладает способностью указывать на область любого размера после его типизирования каким-либо объектом, т.е. явным указанием типа.

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

Знак '*' является унарной операцией косвенной адресации, его операнд – указатель, а результат – адрес объекта, на который указывает операнд. Адресация является косвенной, так как обращение к области памяти осуществляется не напрямую по адресу (например, 1А2В), а через объект, которому в памяти соответствует определенный участок. Объем памяти, который выделяется для хранения данных, определяется типом данных и моделью памяти. Для приведенной на рисунке 2 модели памяти адресом переменной типа float с именем summa является 0012FF48, адресом переменной типа int с именем date является 0012FF54, адресом переменной типа char с именем ch является 0012FF63.

 

Рисунок 10. 2 Адресация типов в С

Примеры определения указателей:

int *P;

/*указатель Р может содержать адрес объекта типа int*/

float *s;

/*указатель s может содержать адрес объекта типа float*/

Синтаксис объявления указателя на объект базового типа:

Тип*ИмяУказателя;

где ИмяУказателя – идентификатор.

Например,

char *s; //переменная s – указатель на объект типа char

double *x; /*переменная х – указатель на объект типа

double, вещественного числа с плавающей

точкой удвоенной точности*/

int *k, *ff; //k, ff – указатели на объекты целого типа

int *p, y; /*р – указатель на объект типа int,

y – целочисленная переменная и не является

указателем*/

int x, *p; /*х – целочисленная переменная и не является

указателем,

р – указатель на объект типа int*/

Указатель может быть константой или переменной, а также указывать на константу или переменную.

Например:

int i;//целая переменная

const int ci=1; //целая константа

 

int *pi; //указатель на целую переменную

const int *pci; //указатель на целую константу

 

int *const cpi; //указатель-константа на целую переменную

const int *const cpc;

//указатель-константа на целую константу

При объявлении указателя его можно сразу проинициализировать (задать значение):

int *pi=&i; //указатель на целую переменную

азателя, а если он находится слева от типа (т.е. слева от *), то он запрещает изменение значения, на которое указывает указатель.

Способы инициализации указателя

  1. Присваивание указателю адреса области памяти существующего объекта:
    • с помощью операции получения адреса:

int a=5;

int *p=&a;

    • с помощью проинициализированного указателя

int *r=p;

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

char *cp=(char*)0х В800 0000;

где 0х В800 0000 – шестнадцатеричная константа, ( char* ) – операция приведения типа.

  1. Присваивание указателю пустого значения:

int *N=NULL; или int *N=0;

Спецификатор указателя при форматированном выводе

Если на экран необходимо вывести адрес, следует применять спецификатор %p.

%p – спецификатор указателя.

Этот спецификатор формата заставляет функцию printf() выводить на экран адрес, формат которого совместим с типом адресации, принятой в компьютере.

Операции с указателями

С указателями можно выполнять следующие операции:

  • разыменование (*) – получение значения величины, адрес которой хранится в указателе;
  • взятие адреса (&);
  • присваивание;
  • арифметические операции
    • сложение указателя только с константой,
    • вычитание: допускается разность указателей и разность указателя и константы,
    • инкремент (++) увеличивает значение указателя на величину sizeof(тип);
    • декремент (--) уменьшает значение указателя на величину sizeof(тип);
  • сравнение;
  • приведение типов.

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

Вариант программы на С:

// Выбор данных из памяти с помощью разных указателей

// Использование функций приведения типов

#include <stdio.h>

#include <conio.h>

int _main(void)

{

unsigned long L=12345678;

char *cp=(char*)&L;

int *ip=(int*)&L;

long *lp=(long*)&L;

 

printf("\n&L =%p",&L);

printf("\nL = %d",L);

printf("\n*cp = %c",*cp);

printf("\n*ip = %d",*ip);

printf("\n*lp = %d",*lp);

 

 

_getch();

return 0;

}

Вариант программы на С++:

#include "stdafx.h"

#include <iostream>

using namespace std;

int _tmain(int argc, _TCHAR* argv[]){

unsigned long L=12345678;

char *cp=(char*)&L;

int *ip=(int*)&L;

long *lp=(long*)&L;

 

cout <<"\n&L = "<<&L;

cout <<"\nL = "<<L;

cout <<"\n*cp = "<<*cp;

cout <<"\n*ip = "<<*ip;

cout <<"\n*lp = "<<*lp;

 

system("pause");

return 0;

}