Главная arrow Начинающим arrow FAQ по языку Си arrow 7. Что такое указатель и для чего он нужен?  
28.05.2017 г.
Главная
Проекты
Статьи
Начинающим
Архив новостей
Ссылки
Контакты
Поиск
Файлы
Форум
Карта сайта
Авторизация





Забыли пароль?
Ещё не зарегистрированы? Регистрация
Поддержи наш сайт!
Через WebMoney

 R785211844650
 Z210696637574
 E368177590409

Простые устройстваОтличные товары по превосходным ценамОтличные товары по превосходным ценам
7. Что такое указатель и для чего он нужен? Печать E-mail
Рейтинг: / 14
ХудшаяЛучшая 
Автор ARV   
18.12.2009 г.

Указатель - это особый вид переменной. Если обычная переменная хранит значение, то указатель хранит адрес ячейки памяти, в которых что-то хранится. От обычных переменных указатель можно отличить по символу «звездочка» перед идентификатором при определении указателя:

int *iptr; // указатель iptr на переменную типа int
char *str; // указатель str на символ

Следует разделять значение указателя и значение по указателю. Значение указателя есть адрес ячейки, а значение по указателю - значение из ячеек по этому адресу. Значение указателю надо присваивать с использованием оператора взятия адреса переменной &:

int *iptr; // объявляем указатель на int
int var1, var2; // объявляем 2 переменных типа int
iptr = &var2; // задаем значение указателя iptr равным адресу переменной var2

Теперь обращение по указателю iptr приведет к тому, что будет использовано значение переменной var2. Кстати, можно присвоить указателю и константное значение, т.е. так:

iptr = 0x012F;

Но в этом случае во-первых, компилятор выдаст предупреждение, а во-вторых, вы должны четко осознавать последствия работы со значением памяти, на которую этот указатель указывает, т.е. с ячейками по адресу 0x012F. Кстати, избежать предупреждения компилятора можно очень просто: задав принудительно тип константы, как «пустой указатель», т.е. указатель, который указывает «куда-то»:

iptr = (void*)0x012F;

 

Для обращения по указателю используется операция разименования указателя, выражающаяся в том, перед идентификатором указателя записывается символ «звездочка»:

*iptr = 12; // теперь окажется, что var2 == 12

Значение по указателю можно использовать, как обычную переменную, т.е. для работы с ним можно использовать все операторы, допустимые для переменных. А вот с операциями над самим указателем есть ряд тонкостей, главная из которых заключается в том, что указатель изменяется на величину, кратную размеру в байтах того типа, на который он указывает. Рассмотрим пример:

int *iptr = (void*)0x100;
iptr++;
int *nptr = iptr;

Вопрос: чему равен nptr? Правильный ответ не 0x101, а 0x102, так как размер типа int равен 2 байта.

Самое интересное, что в Си нет разницы между указателем и массивом, кроме как в форме определения переменных! Следующие 2 определения абсолютно идентичны:

char *str; // указатель на строку
char str[]; // массив символов

Соответственно, идентификатор любого массива есть ни что иное, как указатель на данные, тип которых определен при описании массива. Отсюда вытекает ряд способов использования указателя по аналогии с массивом, например, можно обращаться по указателю:

int *iptr = (void*)0x100;
*iptr = 9;
iptr[1] = 10;
iptr[2] = 11;

В результате выполнения этих операторов окажется, что в памяти по адресу 0x100 хранится число 9, по адресу 0x102 хранится 10 и по адресу 0x104 хранится 11.

Использование указателей позволяет манипулировать содержимым памяти данных совершенно произвольным образом! Именно эта возможность является одним из наиболее сильных средств языка Си, и именно с этой возможностью связано наибольшее количество проблем в программах, на Си написанных!

char array[10] = {1,2,3,4,5,6,7,8,9,10};
int var = 10;
long *lptr = (void*)array;
lptr[2] = 12;

В приведенном примере нет ни одной ошибки, но к каким последствиям он приведет?! «Неожиданно» переменная var окажется обнуленной...


Добавить в любимые (0) | Просмотров: 9841

  Коментарии (2)
 1 Написал(а) Настоящее имя, в 09:53 21.10.2011
так и не понял, почему же var окажется обнуленной??? :?
 2 Написал(а) Настоящее имя, в 10:19 21.10.2011
кажись понял...наверное потому что мы переопределили символьный масив в long, отсюда число 12 запишется начиная с 9,10 + 2 байта, что перезапишет var...

Только зарегистрированные пользователи могут оставлять коментарии.
Пожалуйста зарегистрируйтесь или войдите в ваш аккаунт.

 
« Пред.   След. »
Полезные материалы по сходным темам
Кто на сайте?
Помощь on-line
BannerFans.com