Выражения с указателями

Можно присваивать один указатель другому, но эта операция имеет смысл только в том случае, если оба указателя адресуют один и тот же тип, например

{ int i=123 *pi1=&i, *pi2;

// присваиваем указателю pi2 значение указателя pi1

pi2=pi1;

//выведем значения указателей:

printf(“ %p %p”, pi1, pi2);

}

В результате мы получим одно и то же значение адреса.

Указатели могут встречаться в выражениях, например:

int x=5, y, *px=&x;

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

Приоритет у унарной операции разадресации * выше, чем у бинарных арифметических операций, поэтому при вычислении выражения *px + 5 вначале будет извлечено содержимое по адресу, хранящемуся в р ( то есть получено значение 5), а затем будет выполнена бинарная операция сложения.

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

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

++ инкремента

- - декремента

+, - сложения и вычитания

Если к указателю применяются операции ++ или --, то указатель увеличивается или уменьшается на размер объекта, который он адресует:

тип *ptr;

ptr ++ = значение ptr + sizeof (тип)

ptr -- = значение ptr - sizeof (тип)

Например:

int i, *pi = &i;

float a, *pa =&a;

pi++; //значение указателя pi увеличивается на 2 байта, так как он адресует объект

//типа int, указатель сдвигается вправо на 2 байта

pa++; // значение указателя pa увеличивается на 4 байта, так как он адресует объект

//типа float, указатель сдвигается вправо на 4 байта

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

тип *ptr;

int n;

ptr + n = значение ptr + n*размер типа

Например,

float a, *pa = &a;

pa = pa+3; // значение указателя pa будет увеличено на 12 байт (сдвиг указателя вправо)

Левым операндом операции вычитания может быть указатель, а правым операндом должно быть целое число:

тип *ptr;

int n;

ptr - n = значение ptr - n*размер типа

Например:

int i, *pi = &i;

pi=pi-5; // уменьшение значения указателя на 10 байт (сдвиг указателя влево)

Пример 3.Использование указателей в выражениях

#include <stdio.h>

void main (void)

{

int x=5,y,*px=&x; //указатель px инициализирован адресом переменной x

y=*px+5;

printf("y=%d значение указателя=%p\n",y,px);

y=*px++; //изменение значения указателя после его использования

printf("y=%d значение указателя=%p\n",y,px);

px=&x;

y=(*px)++; //изменение содержимого по адресу, хранящемуся в px

printf("y=%d значение указателя=%p значение, адресуемое указателем *px= %d\n",y,px,*px);

y=++*px; //изменение содержимого по адресу px на единицу

printf("y=%d значение указателя=%p\n",y,px);

}

Результаты работы этой программы имеют вид:

y=10 значение указателя=1561:1000

y=5 значение указателя=1561:1002

y=5 значение указателя=1561:1000 значение, адресуемое указателем*px= 6

y=7 значение указателя=1561:1000

УКАЗАТЕЛИ И МАССИВЫ

Между указателями и массивами существует прямая связь. Когда объявляется массив, например:

int arr [5];

то идентификатор массива arr определяется как константный указатель на первый (с индексом 0) элемент массива. Это означает, что имя массива содержит адрес элемента массива с индексом 0:

arr = &arr[0];

Так как идентификатор массива содержит адрес, то можно, например, записать:

int arr[ 5]; //объявление массива целых

int *parr; //объявление указателя на данное целого типа

parr = arr; // присваивавание указателю адреса первого элемента массива, то же, что

// и parr = &arr[0];

Связь между именем массива arr и указателем parr можно изобразить следующим образом:

 
  Выражения с указателями - student2.ru


arr[0] arr[1] arr[2] arr[3] arr[4]

Адрес элемента массива с индексом i может быть записан как

&arr[i], что эквивалентно записи parr+i

Значение элемента массива с индексом i может быть записано как

arr[i], что эквивалентно записи *(parr+i) или *(arr+i)

Все индексные выражения вида arr[i] компилятор преобразует к адресному представлению в соответствии с правилами выполнения операции сложения указателя с целой величиной:

arr[i]=*(arr+i) =* (arr + i* sizeof(int))

ВАЖНО.

Указатель – это переменная, и ее значение можно изменять в программе, например, можно записать:

parr++;

Операция parr++ означает сдвиг указателя на следующий элемент массива arr++, то есть на 2 байта. Если, например, до выполнения операции parr++ указатель был установлен на первый элемент массива, то в результате выполнения этой операции он окажется установленным на второй элемент:

 
  Выражения с указателями - student2.ru


arr[0] arr[1] arr[2] arr[3] arr[4]

Имя массива – константа. Значение адреса, которое хранит имя массива, изменять нельзя, поэтому ошибочной является следующая запись:

arr++;

Пример 4. Программа, в которой демонстрируется использование указателей на массив.

#include <stdio.h>

#include <conio.h>

#include <stdlib.h>

#include <time.h>

#define N 100 //максимально допустимое количество элементов в массиве

int main(void)

{

int a[N]; /* резервирование памяти под N элементов массива */

int i; //переменная, управляющая циклом

int *pa=a; //объявление указателя на данное целого типа

//и инициализация указателя адресом массива а

clrscr();

randomize();

//цикл заполнения массива случайными числами

for(i=0; i<N; i++)

*(pa+i) = random(101)-50; // присваивание элементу массива значения случайного

// числа из диапазона от -50 до 50

//цикл вывода элементов массива

printf("\n\n Массив выведен по 10 элементов в строке \n\n");

for(i=0; i<N; i++)

{

printf("%6d ", *(pa+i)); // вывод массива

if(i%10==9)

printf("\n");

}

getch();

return 0;

}

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

#include <stdio.h>

#include <conio.h>

void main(void)

{

int i;

int a[10]; //объявление массива целых из десяти элементов

int *pa = a; //объявление указателя на данное целого типа и инициализация указателя

// адресом массива

clrscr();

//цикл ввода элементов массива в диалоговом режиме

for(i=0; i<10; i++)

{

printf("\nВведите элемент массива с индексом %d ",i);

scanf("%d", pa+i); //функция scanf получает адрес элемента массива

}

printf("\n\n Вы ввели массив \n\n");

for(i=0; i<10; i++)

printf("%4d ", *(pa+i)); // вывод массива

getch();

}

Пример 5.Программа, в которой используются указатели на строки.

#include <stdio.h>

void main(void)

{

char s[]="строка как массив";

char *ps=s; //указатель ps инициализирован значением адреса строки s

char *ps1,*ps2,*ps3; //объявление указателей на строки

//присвоение указателю ps1 адреса строковой константы

ps1="В языке си в одну\n"

"строку можно записать\n"

"целое стихотворение\n";

//присвоение указателю ps2 адреса строковой константы

ps2="предложение не будет\

перенесено на следующую строку";

//присвоение указателю ps3 адреса строковой константы

ps3="одна"

" строка";

//цикл вычисления длины строки s, адрес которой хранит указатель ps

// выполнять, пока не найден конец строки

while(*ps!='\0')

ps++;

printf("длина строки= %d\n",ps-s);

puts(ps1);

puts(ps2);

puts(ps3);

}

Наши рекомендации