Меню сайта
Наш опрос
Оцените мой сайт
Всего ответов: 6
Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0
Главная » 2014 » Июль » 22 » Занятие 16. Указатели.
16:02
Занятие 16. Указатели.
Normal 0 false false false RU X-NONE X-NONE MicrosoftInternetExplorer4 Здравствуйте друзья. Сегодня у нас важная и сложная тема. Возможно, самая сложная тема за все время. Указатели.Прежде вспомним основы шестнадцатеричной системы счисления.Любое число в 16-тиричной системе счисления записывается с помощью символов 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F. Шестнадцатеричной она называется, потому что в ней для записи различных чисел используются 16 основных цифр. Например, в привычной нами десятичной системе счисления используется десять основных цифр 0,1,2,3,4,5,6,7,8 и 9.  Первые десять цифр в 16-тиричной системе счисления такие же, как и в десятичной системе, а вот для записи следующих шести используются буквы латинского алфавита.  razmer peremennoi tipa char %d\n", sizeof(char)); printf ("razmer peremennoi tipa int %d\n", sizeof(int)); printf ("razmer peremennoi tipa float %d\n", sizeof(float)); printf ("razmer peremennoi tipa double %d\n", sizeof(double)); return(0); }Результат её работы:Рис 4. Программа иллюстрирующая работу sizeof()У вас данные цифры могут быть другими кстати. Так как стандартом языка не оговаривается какой тип сколько должен занимать в памяти. Оговариваются только из соотношения. Например, размер double не должен быть меньше чем размер float.То есть, если я объявляю в программе переменную типа int, то под нее в памяти выделяется 4 байта (ячейки). Так как мы уже умеем получать адрес переменной, то давайте посмотрим на него. Для того, чтобы вывести число в шестнадцатеричной системе существует специальный спецификатор “%x”. И для него есть модификатор “#” при его записи, шестнадцатеричное число выводится с символами «0х».Листинг16.2 #include <stdio.h> int main (){       int a,b;       printf ("adres peremennoi a %#x\n", &a);       printf ("adres peremennoi b %#x\n", &b); return(0); }Рис.5 Адреса переменных в памятиМы получили два адреса 0x12ff60 и 0x12ff56. По этим адресам в памяти записаны наши переменные a и b. При этом они занимают в памяти по 4 клетки подряд, так как это переменные целого типа и из рисунка 3 видно, что их размер 4 байта. Это выглядит примерно следующим образом.Рис.6. Пример расположения переменных в памятиКак вы уже заметили, переменные в память записываются не одна за другой, а в произвольном месте, лишь бы там было пусто и хватило места. Исключение составляют массивы. Они записываются в память последовательно. Посмотрите на результат работы следующей программы.Листинг16.3#include <stdio.h> int main (){       int a[3];       printf ("adres peremennoi a[0] %#x\n", &a[0]);       printf ("adres peremennoi a[1] %#x\n", &a[1]); return(0); }Рис.7 Расположение массива в памятиВидите, каждый элемент занимает ровно 4 ячейки, потом идет следующий. По порядку и никак иначе. Это важный факт, он иногда используется в программировании. Но сейчас не об этом.Адреса это хорошо, но что с ними делать? На кой чёрт они нам сдались? Обо всем по порядку. Указатели.  Во-первых, для хранения адресов существует специальные переменные, которые называются указателями.  Таким образом, мы вплотную подобрались к теме нашего урока - к указателям. Указатель – переменная, предназначенная для хранения адреса в памяти. Обычно, указатели используют, чтобы хранить адреса других переменных. Объявление указателя.Указатель, раз это переменная, должен как-то объявляться. Делается это почти что также как и обычно.int * p_a;Сначала указывается тип переменной, которая будет храниться в памяти, по адресу указателя. Далее следует специальный символ «*» (звездочка), которая и указывает на то, что мы собираемся объявить не просто переменную типа int, а указатель на переменную типа int. После звездочки пишут имя указателя. Ну и естественно заключительная точка с запятой. В нашем примере, мы объявили  указатель с именем p_a, который будет указывать на переменную типа int. Кстати, обычно, чтобы не путать указатели с другими переменными, в их имена добавляют какой-нибудь отличительный знак. Например, я вот добавляю обычно “p_”.  Когда я вижу в своей программе переменную, имя которой начинается с этих символов, я точно знаю что это у меня указатель. Кроме того, если программа большая, я помимо этого указывают после «p» ещё и тип переменной для типа int  - i, для float – f, для char – с и так далее, получается что-то типа pi_a. Это  сразу говорит мне, что это указатель, который ссылается на переменную типа int.  Присвоение указателю адреса.Давайте перепишем Листинг 16.2, используя указатели.Листинг 16.4#include <stdio.h> int main (){       int a,b,*pi_a, *pi_b;       adres peremennoi a %#x\n", pi_a);       printf ("adres peremennoi b %p\n", pi_b); return(0); }Рис.8. Пример хранения адреса переменной в указателе.Как видите, после объявления с указателем можно работать так же, как и с обычной переменной. Ему можно присвоить некоторый адрес, используя оператор adres peremennoi a %#x\n", pi_a);       printf ("znachenie po adresu zapisannomy v pi_a %d\n", *pi_a); return(0); }Рис.9. Использование указателей для обращения к значениям переменных,на которые они ссылаются Как видите, используя запись *pi_a можно обращаться с указателем, как с переменной соответствующего типа. В нашем случае, как с переменной типа int.Еще раз обсудим звездочку в указателях.Если  звездочка стоит перед именем в объявлении переменной, то в этом случае она означает, что объявляется указатель. Если звездочка встречается внутри программы, то в данном случае, она указывает на то, что мы обращаемся к ячейкам памяти, на которые ссылается указатель.Еще раз внимательно перечитайте предыдущий пункт. Он очень важен, вам необходимо в этом разобраться. Задавайте вопросы в комментариях, если вам что-то непонятно. С этим обязательно нужно хорошо разобраться. Есть еще один специальный указатель. Он имеет свое особое название – нулевой указатель NULL. Нулевой указатель не ссылается никуда. Он используется, чтобы обнулять указатели. Посмотрите на следующую программу.Листинг16.6#include <stdio.h> int main (){       int *pi_a;       printf ("adres peremennoi a %#x\n", pi_a);       adres peremennoi a %#x\n", pi_a); return(0); }Рис.10 Нулевой указательЭто почти все основные действия, которые можно производить  с указателями. Есть еще одно интересное свойство, мы его коснемся чуть позже.И под конец урока. Не зря же мы с вами так долго паримся с этими указателями сегодня. Один небольшой пример. Помните занятие про функции? Или недавнюю небольшую головоломку в группе во Вконтакте.Кто не помнит, вот вам картинка.Рис.11 Простенькая головоломка. Что выведет представленная программа?Нам известно, когда мы передаем переменные в функцию, то передаются не сами переменные, а их копии? Иногда нам это вовсе не нужно. Иногда удобно сделать так, чтобы значения все-таки изменялись. Для этого, нужно передавать в функцию не переменную, а указатель на неё.Давайте перепишем программу с картинки, чтобы она работала так, как и предполагается.Листинг 16.7#include <stdio.h> void obmen (int *pi_a, int*pi_b){ //принимаем указатели на переменные типа int       int temp;       Posle ,x,y); return(0); }Рис.12 Пример работы программы с указателямиКак видите, теперь работает как надо. Если вы внимательно разобрались с началом урока, то проблем с этой программой возникнуть не должно. Если вопросы есть, задавайте в комментариях. Я постараюсь все вам разъяснить. И это еще не все возможности указателей. Следующее занятие снова будет посвящено указателям. Их связью с массивами и строками.Отдельного домашнего задания не будет. Хорошенько разберитесь с этим занятием. Вам должна быть тут понятна каждая строчка. Если интересно, можете потренироваться переводить числа из десятичной системы счисления в шестнадцатеричную, и обратно.  И раз уж мы учимся программировать, то напишите для этого программу. =)))Если вам понравился этот или другие уроки, расскажите пожалуйста о них, своим друзьям Вконтакте,Facebook,Google+, используя кнопки социальных сетей расположенные ниже.
Просмотров: 170 | Добавил: admin | Рейтинг: 0.0/0
Всего комментариев: 0
avatar
Форма входа
Календарь
«  Июль 2014  »
ПнВтСрЧтПтСбВс
 123456
78910111213
14151617181920
21222324252627
28293031
Архив записей