Биохимия спиртового брожения: Основу технологии получения пива составляет спиртовое брожение, - при котором сахар превращается...
Общие условия выбора системы дренажа: Система дренажа выбирается в зависимости от характера защищаемого...
Топ:
Характеристика АТП и сварочно-жестяницкого участка: Транспорт в настоящее время является одной из важнейших отраслей народного хозяйства...
Генеалогическое древо Султанов Османской империи: Османские правители, вначале, будучи еще бейлербеями Анатолии, женились на дочерях византийских императоров...
Интересное:
Национальное богатство страны и его составляющие: для оценки элементов национального богатства используются...
Лечение прогрессирующих форм рака: Одним из наиболее важных достижений экспериментальной химиотерапии опухолей, начатой в 60-х и реализованной в 70-х годах, является...
Уполаживание и террасирование склонов: Если глубина оврага более 5 м необходимо устройство берм. Варианты использования оврагов для градостроительных целей...
Дисциплины:
2023-01-02 | 18 |
5.00
из
|
Заказать работу |
Объединения
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 или ссылается на поле данных класса.
Ссылки
• После инициализации ссылке не может быть присвоена другая переменная.
• Тип ссылки должен совпадать с типом величины, на которую она ссылается.
• Не разрешается определять указатели на ссылки, создавать массивы ссылок и ссылки на ссылки.
Эмиссия газов от очистных сооружений канализации: В последние годы внимание мирового сообщества сосредоточено на экологических проблемах...
Автоматическое растормаживание колес: Тормозные устройства колес предназначены для уменьшения длины пробега и улучшения маневрирования ВС при...
Поперечные профили набережных и береговой полосы: На городских территориях берегоукрепление проектируют с учетом технических и экономических требований, но особое значение придают эстетическим...
Особенности сооружения опор в сложных условиях: Сооружение ВЛ в районах с суровыми климатическими и тяжелыми геологическими условиями...
© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!