Адрес объектов и переменных, указтели и ссылки.
Как переменные расположены в памяти.
Вся память в компьютере состоит из ячеек -
байтов. Все
байты расположены один за другим. Каждый байт имеет свой номер: первый, второй, третий и т.д. Никакой байт не может иметь номер
0.
Разные переменные или объекты дложны поместиться в память. Объект может занять один байт или больше. Например, переменная типа
int может занять 4
байта.
Объекты могут занимать больше или меньше места в памяти. Но
адрес каждого объекта - это номер первого
байта (ячейки) в памяти с которой он размещается. Если объект поместили в память, то на это место никакие другие объекты или переменные уже не размещают.
Для того, работы с адресами нужны специальные переменные:
указатели или
ссылки. Каждая из таких переменных "знает" свой тип переменной или класс объекта, на которы будет указывать.
Указатель "знает"
номер байта и
размер переменной или объекта.
На каждую переменную или объект могут "смотреть" несколько
указателей. Если наша переменная или объект изменилась, ВСЕ
указатели сразу об этом "узнают".
Например.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main(){
int a = 3; // переменная с именем a, где-то лежит в памяти
int *point_to_a; // это указатель на переменны типа int. Получит адрес а, и будет "указывать" на a
int *point2; // это второй указатель на переменные типа int;
// Получим АДРЕС(номер ячейки) переменной a. & - вычисляет адрес
point_to_a = &a;
// И для другой переменной тоже получим ЭТОТ адрес:.
point2 = point_to_a;
// Теперь ОБА указателя "смотрят" на a
// Посмотрим ЗНАЧЕНИЕ a по указателю point_to_a. * перед именем указателя получает ЗНАЧЕНИЕ:
printf("point to a : %d\n",*point_to_a);
// Теперь по указателю point2:
printf("point to a : %d\n",*point2);
// Изменим значение a. Указатели мы не трогаем при этом.
a = 123;
// Посмотрим ЗНАЧЕНИЕ по указателям point_to_a и point2
printf("point to a : %d\n",*point_to_a);
printf("point to a : %d\n",*point2);
// Напечаталось одно и тоже.
//Попробуем изменить переменную через указатель:
*point2 = 255;
// Напечатаем значение a и point_to_a
printf("point to a : %d\n",*point_to_a);
printf("a : %d\n",a);
//Печатается одно и тоже
}
Получим 10 чисел с клавиатуры. Для этого нужен
scanf(). В
scanf() даем переменную с
& - оператор, который вычисляет адрес. Значит в
scanf() можно сразу передать АДРЕС переменной.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main(){
int k;// переменная для числа
int *pk; //УКАЗАТЕЛЬ - переменная для адреса (номера ячейки)
int sum = 0; // для суммы
int i; // счетчик
// положили в УКАЗАТЕЛЬ pk АДРЕС (номер ячейки) k
pk = &k;
for (i = 0; i< 10; i++){
// для scanf нужен АДРЕС переменной
// даем адрес переменной k
// этот адрес лежит в pk
scanf("%d",pk);
// значение из scanf попало по адресу pk
// в переменную k
// сложим это число
sum += k;
// напечатаем
printf("k = %d sum = %d\n",k,sum);
}
}
Можно работать и с буквами
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main(){
char c; // здесь будут лежать буквы
char *pc; // указатель (АДРЕС) на переменную с буквой
int i; // счетчик
// положили АДРЕС (номер ячейки) переменной c в указатель pc
pc = &c;
for (i = 0; i< 10; i++){
scanf("%c",pc);
if (c == 'A'){
printf("%c\n",c);
}
}
}
Теперь мы можем использовать указатели и ссылки в функциях:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
// В эту функцию параметры передаются как "обычно". В этом случает в функцию попадают КОПИИИ переменных
// А сам переменные в функции не используются
void swap1(int a, int b){
int c;
c = a;
a = b;
b = c;
};
// В эту функцию параметры передаются "по ссылке". В этом случает в функцию попадают САМИ переменные
// Они будут изменены во время работы функции int& a - тоже адрес переменной, но чтобы получить
// значение, не нужно писать * перед именем
void swap(int* a, int* b){
int c;
c = *a;
*a = *b;
*b = c;
};
int main(){
int a = 5,b = 7;
swap1(a,b);
// Ничего не изменилось
printf("a = %d b = %d\n",a,b);
// Переменные поменялись местами
swap(&a,&b);
printf("a = %d b = %d\n",a,b);
}
Задача 1
Даны два числа
а и
b. Написать функцию
void min(int * a, int * b), которая находит минимальное число из
a и
b и
кладет в
а это минимальное число, а в
b другое число.
Задача 2
Даны два числа
а и
b. Написать функцию
void plus_minus(int* a, int *b), которая
кладет в
а сумму этих чисел
(*a + *b), а в
b - разность
(*a - *b).
Массивы .
Известно, что в С можно составлять массивы из "обычных" переменных. Каждый элемент массива имеет номер. По номеру массива мы знаем
что там находится.
Массивы можно составлять и из объектов классов.
Каждый массив располагает свои элементы в памяти последовательно.
Имя массива - это АДРЕС его первого элемента.
Задача про точки
Допустим у нас есть прямая, на которой отмечены 5 точек. Необходимо
- получить значения всех точек
- печатать все эти значения
- вычислять растояния можду точками
- искать две точки с наименьшим расстоянием
Задача 3
Напечатать расстояние от точки с номером 0 до точки с номером N.
Задача 4
Напечатать расстояние от точки с номером K до точки с номером N.
Задача 5
Напечатать самую правую точку (max)
Задача 6
Напечатать самую левую точку (min)
Задача 7
1. Напечатать все расстояния от точки с номером 0.
2. Вычислить среднее расстояние от точки m[0] до всех остальных точек (Сложить все расстояния и разделить на 5)
Задача 8
Напечатать минимальное расстояние от точки с номером 0 и напечатать номер такой точки (кроме 0).
Задача 9
Напечатать минимальное расстояние от точки с номером 0 и сколько точек лежат на этом расстоянии (кроме 0).
Задача 10
Напечатать минимальное расстояние от точки с номером 0 и напечатать номера точек, которые лежат на этом расстоянии (кроме 0).
Задача 11
Напечатать расстояние между самой левой и самой правой точкой.
--
TatyanaOvsyannikova2011 - 30 Oct 2015