Выражения с указателями
Можно присваивать один указатель другому, но эта операция имеет смысл только в том случае, если оба указателя адресуют один и тот же тип, например
{ 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 можно изобразить следующим образом:
Адрес элемента массива с индексом 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++ указатель был установлен на первый элемент массива, то в результате выполнения этой операции он окажется установленным на второй элемент:
Имя массива – константа. Значение адреса, которое хранит имя массива, изменять нельзя, поэтому ошибочной является следующая запись:
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); }
Популярное: Почему двоичная система счисления так распространена?: Каждая цифра должна быть как-то представлена на физическом носителе... Личность ребенка как объект и субъект в образовательной технологии: В настоящее время в России идет становление новой системы образования, ориентированного на вхождение... Модели организации как закрытой, открытой, частично открытой системы: Закрытая система имеет жесткие фиксированные границы, ее действия относительно независимы... ©2015-2024 megaobuchalka.ru Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. (538)
|
Почему 1285321 студент выбрали МегаОбучалку... Система поиска информации Мобильная версия сайта Удобная навигация Нет шокирующей рекламы |