Для доступа к членам объединения используются те же синтаксические конструкции, что и для доступа к членам структуры. — КиберПедия 

Индивидуальные и групповые автопоилки: для животных. Схемы и конструкции...

История создания датчика движения: Первый прибор для обнаружения движения был изобретен немецким физиком Генрихом Герцем...

Для доступа к членам объединения используются те же синтаксические конструкции, что и для доступа к членам структуры.

2023-01-02 17
Для доступа к членам объединения используются те же синтаксические конструкции, что и для доступа к членам структуры. 0.00 из 5.00 0 оценок
Заказать работу

Объединения

union tank{

struct {

int x,y;

int fuel;

};

int t[3];

} t34;

t34.x = 5;

t34.y = 1;

t34.fuel = 20;

cout << t34.t[0] << "\n";

cout << t34.t[1] << "\n";

cout << t34.t[2] << "\n";

Указатели
Адресная арифметика

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

• Для хранения адресов в С++ используются специальные типы данных – указатели и ссылки.

• Указатель – это переменная, в которой хранится адрес некоторого объекта программы: другой переменной, поименованной константы, подпрограммы и т.п.

Указатели

В С++ есть три вида указателей, отличающихся свойствами и набором допустимых операций:

– типизированные указатели,

– бестиповые указатели,

– указатели на функции.

[ < Изменяемость значения > ][ < Тип данных>]          [<Тип>] [<Изменяемость указателя>]                          *<Имя>[=<Значение>];

Примеры объявления указателей:

int * ip 1, * ip 2;

double *dp;

void *p;

int (*fun) (double, double);

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

int *a, b, *c;

long *lp, lp2;

float fp, * fp 2;

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

Нетипизированные – создаются как бы «на все случаи жизни». Они отличаются от типизированных указателей отсутствием сведений о размере соответствующего участка памяти.

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

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

int i=3,j=4;

const int n=5;

int * pi;

const int * pi 1; // указатель на константу

int const * pi 11; // указатель на константу

int * const pi 2=& j; // константный указатель

const int * const pi3=&n;

// константный указатель на константу

Обычный указатель pi может менять в процессе работы программы как свое значение, так и значение объектов, на которые он указывает. Его нельзя инициализировать адресом константного объекта, поскольку в противном случае можно было бы модифицировать значение константы косвенно:

pi =& i; // верно

pi =& n; // ошибка!

pi = pi 1; // ошибка!

pi = pi 2; // верно

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

pi1=&n;

cout<<*pi1; // верно

pi1=&j;

* pi 1=7; // ошибка!

Константный указатель pi2, напротив, должен (как и любая константа) инициализироваться при объявлении. Менять свое значение в процессе работы он не может:

* pi 2=7; // верно

pi 2=& j; // ошибка!

Константный указатель на константу pi3 не может модифицировать ни свое значение, ни значение указываемого им объекта.

Инициализация указателей

Присваивание указателю адреса существующего объекта:

•     с помощью операции получения адреса:

int a = 5; // целая переменная

int *p = &a;

//в указатель записывается адрес a

int *p (&a);

// то же самое другим способом

•     значения другого инициализированного указателя:

int *r = p;

Инициализация указателей

• имени массива или функции, которые трактуются как адрес:

int b[10];           // массив

int *t = b;   

// присваивание имени массива

...

void f(int a){ /* … */ }

// определение функции

void (*pf)(int);

// указатель на функцию

pf = f;             

// присваивание имени функции

Инициализация указателей

Присваивание пустого значения:

int *suxx = NULL; // не рекомендуется

int *rulez = 0; // так - лучше

Указатели, инициализированные значением 0, называются нулевыми и ни на что не указывают.

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

int *n = new int;       

int *m = new int (10);        

int *q = new int [10];        

int *u = (int*)malloc(sizeof(int));

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

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

• разыменование (*),

• присваивание,

• сложение с константой,

• вычитание,

• инкремент (++), декремент (- -),

• сравнение,

• приведение типов,

• операция получения адреса (&).

Операция разыменования

• Операция разыменования или косвенная адресация, предназначена для доступа к величине, адрес которой хранится в указателе.

• Эту операцию можно использовать как для получения, так и для изменения значения величины (если она не объявлена как константа):

char a; char *p = new char;

*p = 'Ю'; a = *p;

Операция разыменования

short c, a=5,*ptri=&a;

float d,p=2.4563;

void *b=&a;

c=*ptri;

// в результате с=5

*ptri=125;

// вместо 5 в память переменной а

// теперь записано число 125

Операция разыменования

int x = 1, y = 2;

int * ptr;

//объявили указатель на целую переменную

ptr = & x;

// взяли адрес переменной х = 2

y = * ptr;

// переменная y стала равной 1

* ptr = 0;

// переменная х стала равной 0

Операция разыменования

Нетипизированные указатели разыменовывать нельзя.

• При необходимости разыменовать нетипизированный указатель требуется явно указать тип данных, например:

int c, a=5, *ptri=&a;

void *b=&a;

* b = 6; Þ *(int*)b=6;

Операция разыменования

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

char* s;

*s= ’a’; // ошибка!

cin >> s; // ошибка!

Присваивание указателей

• Присваивание без явного приведения типов допускается только

– указателям типа void*

–  если тип указателей справа и слева от операции присваивания один и тот же.

• Присваивание типизированных указателей указателям функций (и наоборот) недопустимо.

Присваивание указателей

int a,*ptri,*ptrj; void *b;

ptri=&a;      

*ptri=0;

ptri=ptrj;

b=&a;

ptri = b; Þ ptri=(int *) b;

Присваивание указателей

int *p1,*p2;

float *p3,*p4;

void *p;

// допустимые операции

p1=p2; p4=p3; p1=0; p=NULL;

// недопустимые операции

p3=p2; p1=p3;

// явное переопределение типа

p3=(float*)p2; p1=(int*)p3;

Присваивание указателей

#include <stdio.h>

int main() {

double x = 200.35, y;

int *p;

p = (int *)&x; / / здесь явное преобразование

/ / типов необходимо, так как &x ссылается на

/ / double, а p имеет тип *int

y = *p; / / ожидается, что y будет присвоено

/ / значение 200.35

printf("значение x равно %f \n", x);

printf("значение x равно %f", y);

return 0;

}

Получение адреса (&)

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

–  при помощи операции присваивания:

int *pi,i=10;

pi=&i;

–  во время инициализации указателя при его объявлении:

float b=5.7,*pf=&b;

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

Арифметические операции

• Сложение с целым, вычитание, инкремент и декремент автоматически учитывают размер типа величин, адресуемых указателями.

• Эти операции применимы только к типизированным указателям одного типа и имеют смысл в основном при работе со структурами данных, последовательно размещенными в памяти, например, с массивами.

Адресная арифметика

• Совокупность указанных операций и правила выполнения этих операций над указателями получили название адресной арифметики.

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

<Указатель> + n Û <Адрес> + n*sizeof(<Тип данных>)

Адресная арифметика

short a, *ptrs =&a;

ptrs++;

ptrs+=4;

*(ptrs+2)=2;

Адресная арифметика

• Разность двух указателей - это разность их значений, деленная на размер типа в байтах.

Из равенства p+n==p1 следует, что p1-p==n.

• Значением оператора разности двух указателей является целое, равное количеству объектов рассматриваемого типа между адресами от p до p1.

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

Адресная арифметика

Инкремент перемещает указатель к следующему объекту рассматриваемого типа, декремент - к предыдущему.

• Два указателя можно сравнивать между собой, используя операторы отношения

 >, <, >=, <=, ==,!=.

if(p < q)

printf("p ссылается на меньший адрес, чем q");

Адресная арифметика

int main (void) {

int x, y;

int *px, *py;

ptrdiff _ t z;

// Взятие адресов переменных

px = & x;

py = & y;

// Разница двух указателей

z = px - py;

printf("\n The difference of two pointers to %p and %p is: %d", px, py, (int) z);

printf("\n\n The addresses are: px = %p, py = %p\n", &px, &py);    

printf("\n Press any key: ");

_getch();

return 0;

}

Ссылки

• Кроме указателя в С++ для хранения адреса может использоваться ссылка.

• Ссылка определена как альтернативное имя уже существующего объекта.

•  Основные достоинства ссылок проявляются при работе с возвращаемыми параметрами функций.

• Правила описания ссылок:

<Тип данных> &<Имя>[= <Выражение>] или

<Тип данных> &<Имя>[(<Выражение>)]

Ссылки

int L=127;

int &SL=L; // первая форма

int &SL(L); // вторая форма

int kol;

int &pal = kol;

const char &CR = '\n';

Int a, // переменная

 *ptri=&a, // указатель

 &b=a; // ссылка

a=3; Û *ptri=3;  b=3

Ссылки

• Ссылка - это синоним имени объекта, или псевдоним, или ярлык.

• Сама ссылка объектом не является, поэтому память для нее не выделяется.

•  Поскольку ссылка является другим именем объекта, все операции со ссылкой выполняются на самом деле с самим объектом.

• Ссылки подчиняются общим правилам определения области видимости, действия и времени жизни.

Ссылки

• Указатель содержит адрес и при работе с адресуемыми им данными необходимо использовать операцию разыменования.

• Ссылка объявляется как альтернативное имя, поэтому при работе с данными по ссылке разыменование не нужно.

• Переменная-ссылка должна явно инициализироваться при ее описании, кроме случаев, когда она является параметром функции, описана как extern или ссылается на поле данных класса.

Ссылки

• После инициализации ссылке не может быть присвоена другая переменная.

• Тип ссылки должен совпадать с типом величины, на которую она ссылается.

• Не разрешается определять указатели на ссылки, создавать массивы ссылок и ссылки на ссылки.


Поделиться с друзьями:

Типы сооружений для обработки осадков: Септиками называются сооружения, в которых одновременно происходят осветление сточной жидкости...

Биохимия спиртового брожения: Основу технологии получения пива составляет спиртовое брожение, - при котором сахар превращается...

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

История развития хранилищ для нефти: Первые склады нефти появились в XVII веке. Они представляли собой землянные ямы-амбара глубиной 4…5 м...



© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!

0.102 с.