Использование указателей для связи функций
В функцию можно передавать не только значения переменных, но и их адреса. В этом случае в вызываемой функции можно изменять значение локальных переменных, определенных в вызывающей функции.
void swap(int*,int*);
void main(void){
int x=5, y=10;
printf ("Прервичные значения х=%d, y=%d\n",x, y);
swap (&x, &y);
printf ("Новые значения х=%d, y=%d\n", x, y);
}
void swap (int*v, int*z){
int u;
u=*v;
*v=*z; //x=y
*z=u;
}
Мы передали в функцию адреса переменных, поэтому при выходе х, у имееют новые значения. При передаче значений этого не происходило.
Вызов swap (x, y); swap (&x, &y);
Определение функции swap (int v, int z); swap (int*v, int*z);
Переменные х, y являются локальными в функции main, но мы, таким образом, можем на них воздействовать в другой функции.
Указатели на одномерные массивы
Указатели позволяют эффективно работать с массивами. Имя массива представляет собой скрытую форму указателя.
Mas -> &mas[0]; - определяется адрес 1-го элемента массива. Оба выражения являются константными выражениями и не меняются на протяжении работы программы. Их можно присваивать переменной типа указатель.
void main(void){
int dates [4], *pti, i;
float bills [4], *ptf;
pti=dates;
ptf=bills;
for (i=0; i<4; i++)
printf ("указатель +%d: %10u и %10u\n", i, pti+i; ptf+i);
}
Указатель +0: 56014 56026 - начало адреса массивов.
+1: 56016 56030
+2: 56018 56034
+3: 56020 56038
Прибавляя 1 к указателю, переходим к следующему элементу массива, а не к следующему байту, т.е. смещаемся на длину типа элемента массива.
рt pt+1 pt+2 pt+3
dates+2 <=> &dates[2]
*(dates+2) <=> dates[2]
*dates+2 <=> *(dates)+2
//Суммирование элементов массива с использованием указателя.
for(i=0;i<10; i++)
sum+=*(ptm+i);
или
for(i=0;i<10; i++){
sum+=*ptm;
ptm++;
}
или
for(i=0;i<10; i++)
sum+=*ptm++;
Указатели на многомерные массивы
Указателю можно присвоить адрес на массив
int mas[2][2], *pti;
pti=mas[0]; //pti=&mas[0][0]
pti+1<=>&mas[0][1]; //так как элементы массива расположены в
pti+2<=>&mas[1][0]; //памяти последовательно и сначала
//меняется второй индекс.
Для двумерного массива:
mas[0]<=> &mas[0][0];
mas[1] <=>&mas[1][0]; //Это важное свойство, потому что можно
//работать с 2-м массивом как с одномерным.
Операции над указателями
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 увеличение адреса на длину типа.
++рх;
4. сравнение указателей ==, !=, >=, <=, >, <
//Пример программы копирования двух массивов
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 допустимо, но неопределено. Использование указателя на элемент вне массива ведет к непредсказуемым результатам работы программы. Контроль за допустимыми значениями указателей возлагается на программиста.