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


1. Присвоить ему значение адреса
int*px, x=2; px=&x;
2. Можно присвоить константу — адрес ячейки с описанием состояния аппаратных средств — абсолютный адрес.
3. После присвоения адреса можно применять операцию взятия косвенного адреса. 
px=&x; y=*px; //y==x; Приоритет выше чем y =
*px=10; x=10;
4. *px+2 //к значению переменной, адрес которой в px, прибавить 2.
рх++; // рх+1 увеличение адреса на длину типа.
++рх;
1. сравнение указателей ==, !=, >=, <=, >, <
//копируем два массива
void main(void) {
char ar1[100], ar2[100];
char *pa1, *pa2;
pa1=&ar1;
pa2=&ar2;
while(pa2<(ar2+sizeof(ar2)))
pa1++=pa2++;
}

Внутренние арифметические операции с указателями зависят от действующей модели памяти и наличия переопределяющих модификаторов указателя. Разность между двумя значениями указателей имеет смысл только в том случае, если оба они указывают на один массив.
Арифметические операции с указателями ограничены сложением, вычитанием и сравнением. Арифметические операции с указателями объектов типа «указатель на тип type» автоматически учитывают размер этого типа, то есть число байт, необходимое для хранения в памяти объекта данного типа.
При выполнении арифметических операций с указателями предпола-гается, что указатель указывает на массив объектов. Таким образом, если указатель объявлен как указатель на type, то прибавление к нему целочисленного значения перемещает указатель на соответствующее количество объектов type. Если type имеет размер 10 байтов, то прибавление целого числа 5 к указателю этого типа перемещает указатель в памяти на 50 байт. Разность представляет собой число элементов массива, разделяющих два значения указателей. Например, если ptr1 указывает на третий элемент массива, а ptr2 на десятый, то результатом выполнения вычитания ptr2 — ptr1 будет 7.
Когда с «указателем на тип type» выполняется операция сложения или вычитания целого числа, то результат также будет «указателем на тип type». Если type не является массивом, то операнд указателя будет рассматриваться как указатель на первый элемент «массива типа type» длиной sizeof(type).
Конечно, такого элемента, как «указатель на следующий за послед-ним элемент», однако указатель может принимать это значение. Если P указывает на последний элемент массива, то значение P+1 допустимо, но неопределено. Если P указывает на элемент за последним элементом мас-сива, то допустимо значение P-1, когда указатель установлен на послед-ний элемент массива. Однако использование указателя на элемент вне массива ведет к непредсказуемым результатам работы программы.
Для информации: P+n можно представить себе как перемещение указа-теля на (n*sizeof(type)) байт вперед, пока указатель остается в допустимых границах (не далее первого за концом массива элемента). Контроль за допустимыми значениями указателей возлагается на программиста.

Передача массива в качестве аргумента в функцию

void main(void){
int age[10];
…………
sum (age);
……….
}
void sum (int year[]){}
Описатель int year[] — создает указатель на массив age. Можно по другому.
void sum (int*pm){}.

pm+3?year[3]?age[3] одно и тоже pm[3].
int* pm и int pm[]; — одно и тоже
Создадим функцию для определения среднего значения в массиве.
float var (int*pm, int i){ //передаем адрес массива и количество
//элементов.
float sum=0;
int k;
for (k=0; k<i; k++)
sum+=*pm++; //*(pm+k)или pm[k]
returm (sum/i); //возвращаем среднее значение в
} //вызывающую функцию.
Void main(void){
int mas[3][4]={ {1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12} };
int i;
for (i=0; i<3; i++)
printf («Среднее значение строки %d равно %4.2f.\n», i+1,
var(mas[i],4));
}
Работаем с двумерным массивом как одномерным, передавая в функцию его адрес и количество элементов. Каждая строка – это одномерный мас-сив.
Если нужно передать массив в функцию как двумерный.
float var(int mas[][4]),т.е. разбивает массив на строки по 4 столбца.

Указатель на void *

Объявление void *vptr; объявляет, что vptr — это родовой указа-тель, которому может быть присвоено любое значение «указатель на тип type» без выдачи компилятором сообщений. Без правильного приведения типов между «указателем на тип type1» и «указателем на тип type2», где type1 и type2 это различные типы, присвоение может вызвать пре-дупреждение или ошибку компилятора. Если type1 это указатель на void, приведения типов не требуется.
int max(void *, void *);
void main(void) {
int x=5, y=10;
int k=max(&x,&y);
(k==0)?puts(«x>Y»): puts(«x<Y»);
}
int max(void *a,void *b) {
return((*a>*b)?0:1);
}

Ограничения присвоения также существуют относительно указателей разных размеров (near, far и huge). Можно присвоить меньший указатель большему, не вызвав ошибки, но нельзя выполнить обратную операцию, не выполнив явную операцию приведения. Например,
char near *ncp;
char far *fcp;
fcp = ncp; // допустимо
ncp = fcp; // недопустимо
ncp = (char near*)fcp; // теперь допустимо