начал главу с указателями, набросок схемы, ссылка на указатели в 04

This commit is contained in:
Ivan I. Ovchinnikov 2021-09-06 12:31:16 +03:00
parent 85d24e586d
commit b3013742e2
3 changed files with 53 additions and 33 deletions

View File

@ -25,52 +25,27 @@
\import{sections/}{07-functions} \import{sections/}{07-functions}
\section{Указатели} \section{Указатели}
% Коллеги, здравствуйте. Вот и пришла пора поговорить о серьёзном низкоуровневом программировании. О том, от чего стараются оградить программистов языки высокого уровня и современные фреймворки. Об указателях. Вот и пришла пора поговорить о серьёзном низкоуровневом программировании. О том, от чего стараются оградить программистов языки высокого уровня и разнообразные фреймворки. \textit{\textbf{Об указателях.}} В этом разделе мы поговорим о том, что такое указатели и как они соотносятся с остальными переменными, что такое передача аргумента по значению и по указателю. Мы уже получили некоторое понятие об указателях (\hyperref[text:pointers]{\ref{text:pointers}}), теперь же, можем поговорить о них подробнее.
% На этом уроке мы поговорим о том, что такое указатели и как они соотносятся с остальными переменными, что такое передача аргумента по значению и по ссылке.
% Как мы наверняка помним, все переменные и константы, используемые в программе, хранятся в оперативной памяти. У каждой переменной и константы в памяти есть свой собственный адрес. Адреса принято показывать на экране в виде шестнадцатиричных чисел. Этот адрес выдаётся нашей программе операционной системой, а язык Си позволяет использовать его на усмотрение программиста. Иными словами в языке С есть возможность получить доступ к переменной не только по имени, но и по адресу. Получение доступа к переменной по адресу называется разыменовыванием. Давайте выведем в консоль всю имеющуюся информацию о переменной «а». Мы знаем, что это целочисленная переменная значением 50, которая хранится по какому-то адресу.
% Адрес переменной может храниться в специальной переменной, которая называется указатель.
% Для объявления указателя пишут тип переменной, адрес которой будет храниться в указателе, знак звёздочки и имя указателя. Такому указателю можно присвоить значение адреса существующей переменной, также как мы делали это раньше с другими типами данных
% Для наглядности снова выведем всю имеющуюся у нас на данный момент информацию на экран. Напомню, для вывода адреса используется заполнитель %p. Выведем в консоль десятичное значение переменной pointer и адрес переменной pointer
% Увидим, что значение переменной pointer является совершенно случайным числом.
% Если мы представим это в виде адреса то всё встанет на свои места. Адрес «а» - это значение переменной pointer.
% СЛАЙД ГДЕ БУКВЫ И ЦИФРЫ ТОРЧАТ ИЗ КОРОБОК С «АДРЕСАМИ»
% СЛАЙД С ПРИМЕРОМ АДРЕСА
Как мы, наверняка, помним, все переменные и константы, используемые в программе, хранятся в оперативной памяти. У каждой переменной и константы в памяти есть свой собственный адрес (они как-то сложно распределяются программой, компилятором, операционной системой и другими участвующими в процессе работы компьютера сущностями). Адреса принято показывать на экране в виде шестнадцатиричных чисел. Для простоты, давайте считать, что этот адрес выдаётся нашей программе операционной системой, а язык С позволяет использовать его на усмотрение программиста. Иными словами, в языке С есть возможность получить доступ к переменной не только по имени, но и по адресу. Получение доступа к переменной по адресу называется \textit{разыменовыванием}.
% РАЗЫМЕНОВЫВАНИЕ (ВОЗМОЖНО КАРТИНКА) % РАЗЫМЕНОВЫВАНИЕ (ВОЗМОЖНО КАРТИНКА)
Давайте выведем в консоль всю имеющуюся информацию о переменной <<а>>. Мы знаем, что это целочисленная переменная со значением 50, которая хранится по какому-то адресу.
% int main (int argc, const char** argv) {
% int a = 50; % int a = 50;
% printf("value of a is %d \n", a); % printf("value of a is %d \n", a);
% printf("address of a is %p \n", &a); % printf("address of a is %p \n", &a);
% Адрес переменной может храниться в специальной переменной, которая называется указатель.
% Для объявления указателя пишут тип переменной, адрес которой будет храниться в указателе, знак звёздочки и имя указателя. Такому указателю можно присвоить значение адреса существующей переменной, также как мы делали это раньше с другими типами данных
% int * pointer; % int * pointer;
% pointer = &a; % pointer = &a;
% Для наглядности снова выведем всю имеющуюся у нас на данный момент информацию на экран. Напомню, для вывода адреса используется заполнитель %p. Выведем в консоль десятичное значение переменной pointer и адрес переменной pointer
% printf("value of pointer is %d \n", pointer); % printf("value of pointer is %d \n", pointer);
% printf("address of pointer is %p \n", &pointer); % printf("address of pointer is %p \n", &pointer);
% Увидим, что значение переменной pointer является совершенно случайным числом.
% Если мы представим это в виде адреса то всё встанет на свои места. Адрес «а» - это значение переменной pointer.
% printf("value of pointer is %d %p \n", pointer); % printf("value of pointer is %d %p \n", pointer);
% Пока что ничего необычного, все эти операции мы выполняли на предыдущих уроках. Но поскольку pointer это необычная переменная, а указатель, то мы можем получить не только её значение, но и значение переменной, на которую она указывает. Давайте запишем, вывести в консоль «переменная pointer указывает на такое-то значение» и разыменуем pointer. Т.е. получим доступ к переменной, на которую ссылается указатель pointer. % Пока что ничего необычного, все эти операции мы выполняли на предыдущих уроках. Но поскольку pointer это необычная переменная, а указатель, то мы можем получить не только её значение, но и значение переменной, на которую она указывает. Давайте запишем, вывести в консоль «переменная pointer указывает на такое-то значение» и разыменуем pointer. Т.е. получим доступ к переменной, на которую ссылается указатель pointer.

44
schemes/pointer.tex Normal file
View File

@ -0,0 +1,44 @@
\tikzset{every picture/.style={line width=0.75pt}} %set default line width to 0.75pt
\begin{tikzpicture}[x=0.75pt,y=0.75pt,yscale=-1,xscale=1]
%uncomment if require: \path (0,460); %set diagram left start at 0, and has height of 460
%Shape: Rectangle [id:dp48909031690071814]
\draw (40,150) -- (199,150) -- (199,220.5) -- (40,220.5) -- cycle ;
%Shape: Rectangle [id:dp3254956575959984]
\draw (222,60) -- (381,60) -- (381,130.5) -- (222,130.5) -- cycle ;
%Shape: Rectangle [id:dp8271767901522998]
\draw (401,151) -- (560,151) -- (560,221.5) -- (401,221.5) -- cycle ;
%Shape: Rectangle [id:dp7663103953587053]
\draw (220,240) -- (379,240) -- (379,310.5) -- (220,310.5) -- cycle ;
%Curve Lines [id:da5551761286150834]
\draw (383,91) .. controls (420.81,62.64) and (422.98,61.51) .. (490.97,150.16) ;
\draw [shift={(492,151.5)}, rotate = 232.52] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ;
%Curve Lines [id:da7602593545992278]
\draw (490,223) .. controls (553.36,260.13) and (430.5,280.1) .. (382.43,290.2) ;
\draw [shift={(381,290.5)}, rotate = 347.99] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ;
%Curve Lines [id:da0637330676841148]
\draw (221,279) .. controls (188.16,311.34) and (187.01,308.53) .. (113.12,223.78) ;
\draw [shift={(112,222.5)}, rotate = 408.90999999999997] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ;
%Curve Lines [id:da9922300811837096]
\draw (121,152) .. controls (86,85.5) and (85,83.5) .. (223,90.5) ;
\draw [shift={(223,90.5)}, rotate = 182.9] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ;
% Text Node
\draw (49,155) node [anchor=north west][inner sep=0.75pt] [align=left] {Значение};
% Text Node
\draw (231,69) node [anchor=north west][inner sep=0.75pt] [align=left] {Переменная \\(идентификатор)};
% Text Node
\draw (413,162) node [anchor=north west][inner sep=0.75pt] [align=left] {Адрес};
% Text Node
\draw (236,251) node [anchor=north west][inner sep=0.75pt] [align=left] {Указатель};
% Text Node
\draw (457,68) node [anchor=north west][inner sep=0.75pt] [align=left] {Хранится по};
% Text Node
\draw (470,272) node [anchor=north west][inner sep=0.75pt] [align=left] {Сохраняется в};
% Text Node
\draw (88,66) node [anchor=north west][inner sep=0.75pt] [align=left] {Получается по};
% Text Node
\draw (65,299) node [anchor=north west][inner sep=0.75pt] [align=left] {Разыменовывается};
\end{tikzpicture}

View File

@ -72,6 +72,7 @@ integers: 1
$ $
\end{verbatim} \end{verbatim}
\end{figure} \end{figure}
\label{text:pointers}
\paragraph{Тип данных - указатель.} Как было сказано - переменная это именованный контейнер. У каждого такого контейнера есть свой собственный адрес в оперативной памяти. Язык С позволяет узнать этот адрес и работать с ним. Оператор взятия адреса это знак амперсанд (\&), написанный перед именем переменной. То есть у любой переменной всегда есть значение и адрес где это значение хранится. Для вывода в консоль адреса используется специальный заполнитель - \code{\%p}. \paragraph{Тип данных - указатель.} Как было сказано - переменная это именованный контейнер. У каждого такого контейнера есть свой собственный адрес в оперативной памяти. Язык С позволяет узнать этот адрес и работать с ним. Оператор взятия адреса это знак амперсанд (\&), написанный перед именем переменной. То есть у любой переменной всегда есть значение и адрес где это значение хранится. Для вывода в консоль адреса используется специальный заполнитель - \code{\%p}.
\begin{figure}[h!] \begin{figure}[h!]