Указатели на объекты
В общем случае синтаксис определения указателя на объект:
Тип*Описатель;
При определении указателя специфицируется имя указателя-переменной (в дальнейшем указатель) и тип объекта, на который он ссылается.
Тип задает тип объекта, адрес которого будет содержать определяемая переменная и может соответствовать базовому, пустому (свободному, то есть типу 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; //указатель на целую переменную
азателя, а если он находится слева от типа (т.е. слева от *), то он запрещает изменение значения, на которое указывает указатель.Способы инициализации указателя
- Присваивание указателю адреса области памяти существующего объекта:
- с помощью операции получения адреса:
int a=5;
int *p=&a;
- с помощью проинициализированного указателя
int *r=p;
- Присваивание указателю адреса области памяти в явном виде:
char *cp=(char*)0х В800 0000;
где 0х В800 0000 – шестнадцатеричная константа, ( char* ) – операция приведения типа.
- Присваивание указателю пустого значения:
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;
}