Указатели и массивы. Пример. Адресные операции


Указатели (или ссылки) используются для представления и обработки адресных данных. В языке С существует сильная взаимосвязь между указателями и массивами, и обычно их рассматривают в едином контексте.

Указатели

Указатели (ссылки) являются в языке типизированными. Они всегда ссылаются на объекты предопределенного типа, за исключением, когда явно указан в декларации тип void.

Пример

int *p; /*указатель на объекты типа int*/

double *pp; /*указатель на объект типа double*/

void *pnt; /*указатель на объект любого типа*/

Далее в программе может быть выполнено:

pnt = pp;

Но тогда обращение к pnt в программе должно быть такое:

…(double*)pnt …

или

pnt = p;

и обращение

…(int*)pnt…

То, что в скобках – это оператор приведения типа. В последнем случае void* к типу int*.

К указателям применима в выражениях операция *, которая дает значение объекта, на который ссылается указатель.

 

Пример

int x = 1;

int y, *px = &x; /* px указывает на переменную x */

……….

y = *px+1; /* y присваивается значение 2*/

*px = *px + y; /* x получает значение 3 */

К значению, на которое ссылался указатель px, добавилась 1, и результат был присвоен переменной y.

 

Двойственной к операции «*» является операция «&», вычисляющая адрес переменной.

Пример

int i;

float x;

char name [80];

scanf(“%d%f%s”, &i, &x, name);

Если во входном потоке содержатся символы: 10 0.3е-2 petroff, то эти значения будут присвоены соответствующим переменным i, x, name.

Функция scanf() обеспечивает форматируемый ввод. 1-й аргумент всегда строка формата. Возвращает всегда количество вводимых элементов (но не символов). Таким образом, может быть организован контроль по вводу. В примере форматы для ввода целого, вещественного и строки символов.

Параметры функции scanf() должны быть ссылками, т.е. содержать адреса переменных, куда будут вводиться данные. Это обусловлено тем, что простые базовые данные передаются по значению, и чтобы записать в переменную значение, в функцию необходимо передать ее адрес, name – это массив. При указании имени массива в выражении всегда вычисляется его адрес и поэтому для массива операция «&» не требуется.

Адресные операции

& - вычисление адреса переменной,

* - доступ к значению переменной через ее адрес, или доступ к некоторой ячейке памяти через адресное выражение.

Пример

double *dp, *func();

dp – указатель, принимающий адрес на (переменные или ячейки, хранящие) тип double,

func() – функция, выдающая указатель на (переменную или ячейку, хранящую) тип double.

Пример

int y, var = 1, *ptr = (int*)200, *ptr1 = &var;

ptr – инициализируется начальным значением 200;

ptr1 – инициализируется адресом переменной var.

…………………………………….

y = *ptr1+1;

……………………………………..

// *ptr1 – извлекается значение по адресу, который содержится в ptr1.

Таким образом, если у будет равно 2.

Пример

Если теперь выполнить:

(*ptr1) = 2;

то переменной var будет присвоено значение 2. Здесь скобки можно и неуказывать, так как приоритет * выше, чем у =.

Пример

*ptr1++; /*увеличение значения указателя на 2 байта*/

Теперь ptr1 будет ссылаться на ячейку, расположенную «за переменной» var.

Возможно, теперь ptr1 ссылается на защищенную область памяти.

Пример

(*ptr1)++; /* увеличение на 1 значения переменной var,

если считать, что предыдущий пример не принимаем во внимание */

Родовой указатель

Таким указателем считается указатель типа void*. Когда void – указатель используется в выражениях, надо явно указать компилятору, к какому конкретно типу приводится этот указатель, что позволит правильно сформировать операции доступа к ячейкам памяти через этот указатель.

Пример

unsigned long block = 0xffecddccL;

void *ptr = █

char ch;

unsigned two_bytes;

long int four_bytes;

ch = *(char*)ptr;

two_bytes = *(unsigned*) ptr;

four_bytes = *(long int*) ptr;

В результате в ch пересылается младший байт переменной block, то есть ch = 0xcc. В переменную two_bytes – 2 байта, - 0xddcc. В переменную four_bytes – 4 байта, - 0xffeeddcc.

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

Пример

Обмен значениями между двумя переменными. Это характерный пример побочного эффекта:

void swap(int *px, int *py)

{ int tmp;

temp =*px;

*px = *py;

*py = temp;

}



Дата добавления: 2016-05-26; просмотров: 1525;


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

Воспользовавшись поиском можно найти нужную информацию на сайте.

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

Считаете данную информацию полезной, тогда расскажите друзьям в соц. сетях.
Poznayka.org - Познайка.Орг - 2016-2024 год. Материал предоставляется для ознакомительных и учебных целей.
Генерация страницы за: 0.009 сек.