ТОР 5 статей: Методические подходы к анализу финансового состояния предприятия Проблема периодизации русской литературы ХХ века. Краткая характеристика второй половины ХХ века Характеристика шлифовальных кругов и ее маркировка Служебные части речи. Предлог. Союз. Частицы КАТЕГОРИИ:
|
Лекция 8. Указатели и массивыУказатели (или ссылки) используются для представления и обработки адресных данных. В языке С существует сильная взаимосвязь между указателями и массивами, и обычно их рассматривают в едином контексте. Указатели Указатели (ссылки) являются в языке типизированными. Они всегда ссылаются на объекты предопределенного типа, за исключением, когда явно указан в декларации тип void. Пример int *p; /*указатель на объекты типа int*/ double *pp; /*указатель на объект типа double*/ void *pnt; /*указатель на объект любого типа*/ Далее в программе может быть выполнено: pnt = pp; Но тогда обращение к pnt в программе должно быть такое: …(double*)pnt … или pnt = p; и обращение …(int*)pnt… То, что в скобках – это оператор приведения типа. В последнем случае void* к типу int*. К указателям применима в выражениях операция *, которая дает значение объекта, на который ссылается указатель.
Пример int x = 1; int y, *px = &x; /* px указывает на переменную x */ ………. y = *px+1; /* y присваивается значение 2*/ *px = *px + y; /* x получает значение 3 */ К значению, на которое ссылался указатель px, добавилась 1, и результат был присвоен переменной y.
Двойственной к операции «*» является операция «&», вычисляющая адрес переменной. Пример int i; float x; char name [80]; scanf(“%d%f%s”, &i, &x, name); Если во входном потоке содержатся символы: 10 0.3е-2 petroff, то эти значения будут присвоены соответствующим переменным i, x, name. Функция scanf() обеспечивает форматируемый ввод. 1-й аргумент всегда строка формата. Возвращает всегда количество вводимых элементов (но не символов). Таким образом, может быть организован контроль по вводу. В примере форматы для ввода целого, вещественного и строки символов. Параметры функции scanf() должны быть ссылками, т.е. содержать адреса переменных, куда будут вводиться данные. Это обусловлено тем, что простые базовые данные передаются по значению, и чтобы записать в переменную значение, в функцию необходимо передать ее адрес, name – это массив. При указании имени массива в выражении всегда вычисляется его адрес и поэтому для массива операция «&» не требуется. Адресные операции & - вычисление адреса переменной, * - доступ к значению переменной через ее адрес, или доступ к некоторой ячейке памяти через адресное выражение. Пример double *dp, *func(); dp – указатель, принимающий адрес на (переменные или ячейки, хранящие) тип double, func() – функция, выдающая указатель на (переменную или ячейку, хранящую) тип double. Пример int y, var = 1, *ptr = (int*)200, *ptr1 = &var; ptr – инициализируется начальным значением 200; ptr1 – инициализируется адресом переменной var. ……………………………………. y = *ptr1+1; …………………………………….. // *ptr1 – извлекается значение по адресу, который содержится в ptr1. Таким образом, если у будет равно 2. Пример Если теперь выполнить: (*ptr1) = 2; то переменной var будет присвоено значение 2. Здесь скобки можно и неуказывать, так как приоритет * выше, чем у =. Пример *ptr1++; /*увеличение значения указателя на 2 байта*/ Теперь ptr1 будет ссылаться на ячейку, расположенную «за переменной» var. Возможно, теперь ptr1 ссылается на защищенную область памяти. Пример (*ptr1)++; /* увеличение на 1 значения переменной var, если считать, что предыдущий пример не принимаем во внимание */ Родовой указатель Таким указателем считается указатель типа void*. Когда void – указатель используется в выражениях, надо явно указать компилятору, к какому конкретно типу приводится этот указатель, что позволит правильно сформировать операции доступа к ячейкам памяти через этот указатель. Пример unsigned long block = 0xffecddccL; void *ptr = █ char ch; unsigned two_bytes; long int four_bytes; ch = *(char*)ptr; two_bytes = *(unsigned*) ptr; four_bytes = *(long int*) ptr; В результате в ch пересылается младший байт переменной block, то есть ch = 0xcc. В переменную two_bytes – 2 байта, - 0xddcc. В переменную four_bytes – 4 байта, - 0xffeeddcc. Одно из назначений указателей – это возможность воздействия на переменные, расположенные вне тела функции. Пример Обмен значениями между двумя переменными. Это характерный пример побочного эффекта: void swap(int *px, int *py) { int tmp; temp =*px; *px = *py; *py = temp; } Не нашли, что искали? Воспользуйтесь поиском:
|