Для чего нужны указатели в программировании

Для чего нужен указатель в Си?

Для чего нужны указатели в программировании. Смотреть фото Для чего нужны указатели в программировании. Смотреть картинку Для чего нужны указатели в программировании. Картинка про Для чего нужны указатели в программировании. Фото Для чего нужны указатели в программировании

Jan 27 · 3 min read

Для чего нужны указатели в программировании. Смотреть фото Для чего нужны указатели в программировании. Смотреть картинку Для чего нужны указатели в программировании. Картинка про Для чего нужны указатели в программировании. Фото Для чего нужны указатели в программировании

Указатель в Си — это переменная, содержащая адрес другой переменной. Сложность указателей заключается в понимании где и для чего они могут пригодиться.

Перед тем, как я начну рассказывать об указателях и зачем они программистам, быстренько вспомним основы:

Указатель

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

Для чего нужен указатель в Си

Функции в Си п ринимают аргументы, передавая или копируя значения в стек функции. Такой метод иногда называется передачей по значению. Поскольку функции в Си и переменные, переданные им, в действительности не связываются, любые внесённые изменения в эти переменные не будут сохраняться за пределами действия функции. Это может вызвать сложности, потому что в некоторых функциях необходимо изменять текущие переменные. Здесь-то нам и пригодится указатель. С его помощью можно получить доступ к памяти, находящейся за пределами стекового кадра. Однако важно отметить, что с помощью указателя можно получить доступ лишь к переменным, расположенным ниже текущего кадра.

В примере выше простая функция с задачей — увеличить на единицу число, проходящее через параметры. Функция написана следующим образом:

Источник

Указатели в C++: зачем нужны, когда использовать и чем отличаются от обращения к объекту напрямую

Для чего нужны указатели в программировании. Смотреть фото Для чего нужны указатели в программировании. Смотреть картинку Для чего нужны указатели в программировании. Картинка про Для чего нужны указатели в программировании. Фото Для чего нужны указатели в программировании

Даже если большинство программистов понимают, в чем разница между объектами и указателями на них, иногда бывает не совсем понятно, в пользу какого из способов обращения к объекту стоит делать выбор. Ниже мы постарались ответить на этот вопрос.

Вопрос

Я заметил, что нередко программисты, чей код я видел, используют указатели на объекты чаще, чем сами эти объекты, т.е., например, используют следующую конструкцию:

Аналогично с методами. Почему вместо этого:

мы должны писать вот это:

Я так понимаю, что это дает выигрыш в скорости, т.к. мы обращаемся напрямую к памяти. Верно? P.S. Я перешел с Java.

Ответ

Заметим, кстати, что в Java указатели не используются в явном виде, т.е. программист не может в коде обратиться к объекту через указатель на него. Однако на деле в Java все типы, кроме базовых, являются ссылочными: обращение к ним происходит по ссылке, хотя явно передать параметр по ссылке нельзя. И еще, на заметку, new в C++ и в Java или C# — абсолютно разные вещи.

Для того, чтобы дать небольшое представление, что же такое указатели в C++, приведем два аналогичных фрагмента кода:

Ближайший эквивалент на C++:

Однако вот это – совершенно другая вещь (C++):

На самом деле, совсем нет. Работа с указателями оформлена в виде кучи, в то время как работа с объектами – это стек, более простая и быстрая структура. Если вы новичок, то у нас для вас есть материал, в котором мы подробно рассказываем, что такое стек и куча.

Строго говоря, этот вопрос объединяет в себе два различных вопроса. Первый: когда стоит использовать динамическое распределение памяти? Второй: когда стоит использовать указатели? Естественно, здесь мы не обойдемся без общих слов о том, что всегда необходимо выбирать наиболее подходящий инструмент для работы. Почти всегда существует реализация лучше, чем с использованием ручного динамического распределения (dynamic allocation) и / или сырых указателей.

Динамическое распределение

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

Указатели

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

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

Источник

Указатели в C++: зачем нужны, когда использовать и чем отличаются

Для чего нужны указатели в программировании. Смотреть фото Для чего нужны указатели в программировании. Смотреть картинку Для чего нужны указатели в программировании. Картинка про Для чего нужны указатели в программировании. Фото Для чего нужны указатели в программировании

Память компьютера — это длинный ряд ячеек. Размер каждой ячейки называется байтом. Байт — это пространство, занятое английским символом алфавита. Объект в обычном понимании — это последовательный набор байтов в памяти. Каждая ячейка имеет адрес, который представляет собой целое число, обычно записанное в шестнадцатеричной форме. Есть три способа доступа к объекту в памяти. Доступ к объекту можно получить с помощью так называемого указателя. Доступ к нему можно получить, используя так называемую ссылку. К нему по-прежнему можно получить доступ с помощью идентификатора. В этой статье основное внимание уделяется использованию указателей и ссылок. В C ++ есть заостренный объект и объект-указатель. У остроконечного предмета есть интересующий предмет. Объект-указатель имеет адрес указанного объекта.

Вам необходимо иметь базовые знания C ++, включая его идентификаторы, функции и массивы; чтобы понять эту статью.

У объекта-указателя и объекта-указателя есть свой идентификатор.

Оператор Address-Of, &

Это унарный оператор. Если за ним следует идентификатор, он возвращает адрес объекта идентификатора. Рассмотрим следующее объявление:

Ниже приведен код, следующее выражение, вернет адрес, идентифицированный ptdInt:

Вам не нужно знать точный адрес (номер) при кодировании.

Оператор косвенного обращения, *

Это унарный оператор в контексте указателей. Обычно он печатается перед идентификатором. Если используется в объявлении идентификатора, то идентификатор является объектом-указателем, который содержит только адрес указанного объекта. Если используется перед идентификатором объекта-указателя, чтобы что-то вернуть, то возвращаемое значение является значением указанного объекта.

Создание указателя

Взгляните на следующий фрагмент кода:

Сегмент начинается с объявления указанного объекта ptdFloat. ptdFloat — это идентификатор, который просто идентифицирует объект с плавающей запятой. Ему мог быть присвоен реальный объект (значение), но в этом случае ему ничего не было присвоено. Далее в сегменте идет объявление объекта-указателя. Оператор косвенного обращения перед этим идентификатором означает, что он должен содержать адрес указанного объекта. Тип объекта, плавающий в начале оператора, означает, что заостренный объект является плавающим. Объект-указатель всегда имеет тот же тип, что и заостренный объект. ptrFoat — это идентификатор, который просто идентифицирует объект-указатель.

В последнем операторе кода адрес указанного объекта присваивается объекту-указателю. Обратите внимание на использование оператора адресации &.

Последний оператор (строка) выше показывает, что после объявления объекта-указателя без инициализации вам не нужен оператор косвенного обращения, когда вам нужно его инициализировать. Фактически, использование оператора косвенного обращения в третьей (последней) строке является синтаксической ошибкой.

Объект-указатель может быть объявлен и инициализирован указанным объектом в одной инструкции, как показано ниже:

Первая строка предыдущего сегмента кода и эта совпадают. Здесь вторая и третья строки предыдущего сегмента кода объединены в один оператор.

Обратите внимание, что в приведенном выше коде при объявлении и инициализации объекта-указателя необходимо использовать оператор косвенного обращения. Однако он не используется, если инициализация должна быть выполнена позже. Объект-указатель инициализируется адресом указанного объекта.

В следующем сегменте кода оператор косвенного обращения используется для возврата содержимого указанного объекта.

В последнем предложении здесь оператор косвенного обращения использовался для возврата значения, на которое указывает идентификатор указателя. Таким образом, при использовании в объявлении идентификатор для оператора косвенного обращения будет содержать адрес указанного объекта. При использовании в выражении возврата в сочетании с идентификатором указателя оператор косвенного обращения возвращает значение указанного объекта.

Присвоение нуля указателю

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

int ptdInt = 5 ;
int * ptrInt = ;

В любом случае указатель (идентификатор) называется нулевым указателем; это означает, что он указывает в никуда. То есть у него нет адреса какого-либо указанного объекта. Здесь 0 — это десятичный ноль, а не шестнадцатеричный ноль. Шестнадцатеричный ноль будет указывать на первый адрес памяти компьютера.

Не пытайтесь получить значение, на которое указывает нулевой указатель. Если вы попробуете это сделать, программа может скомпилироваться, но не запуститься.

Имя массива как постоянный указатель

Рассмотрим следующий массив:

Имя массива arr на самом деле является идентификатором, который имеет адрес первого элемента массива. Следующее выражение возвращает первое значение в массиве:

В случае с массивом оператор приращения ++ ведет себя иначе. Вместо добавления 1 он заменяет адрес указателя на адрес следующего элемента в массиве. Однако имя массива — это постоянный указатель; это означает, что его содержимое (адрес) не может быть изменено или увеличено. Итак, для увеличения начальный адрес массива должен быть назначен непостоянному указателю следующим образом:

Теперь ptr можно увеличивать, чтобы указывать на следующий элемент массива. ptr был объявлен здесь как объект-указатель. Без * здесь не было бы указателя; это будет идентификатор для хранения объекта типа int, а не для хранения адреса памяти.

Следующий сегмент кода, наконец, указывает на четвертый элемент:

Следующий код выводит четвертое значение массива:

Имя функции как идентификатор

Имя функции — это идентификатор функции. Рассмотрим следующее определение функции:

fn — идентификатор функции. Выражение,

возвращает адрес функции в памяти. fn похожа на заостренный объект. Следующее объявление объявляет указатель на функцию:

Идентификатор указанного объекта и идентификатор объекта-указателя различаются. func — это указатель на функцию. fn — идентификатор функции. Итак, func может указывать на fn следующим образом:

Значение (содержание) func — это адрес fn. Два идентификатора могли быть связаны с помощью оператора инициализации следующим образом:

Обратите внимание на различия и сходства в обработке указателей функций и скалярных указателей. func — указатель на функцию; это заостренный объект; он объявлен иначе, чем скалярный указатель.

Функцию можно вызвать с помощью,

Его нельзя вызвать с помощью * func ().

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

#include
using namespace std ;

C++ Reference

Ссылка в C ++ — это просто способ создать синоним (другое имя) для идентификатора. Он использует оператор &, но не так, как & используется для указателей. Рассмотрим следующий фрагмент кода:

cout myInt ‘ \n ‘ ;
cout yourInt ‘ \n ‘ ;

Первый оператор инициализирует идентификатор myInt; т.е. myInt объявлен и содержит значение 8. Второй оператор создает новый идентификатор yourInt, синоним myInt. Для этого в объявлении между типом данных и новым идентификатором помещается оператор &. Операторы cout показывают, что два идентификатора являются синонимами. Чтобы вернуть значение в этом случае, вам не нужно ставить перед ним *. Просто используйте идентификатор.

Здесь myInt и yourInt — это не два разных объекта. Это два разных идентификатора, которые ссылаются (идентифицируют) одно и то же место в памяти, имеющее значение 8. Если значение myInt изменяется, значение yourInt также изменится автоматически. Если значение yourInt изменится, значение myInt также изменится автоматически.

Ссылка на функцию

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

Обратите внимание на первый оператор в функции main, который делает func синонимом fn. Оба ссылаются на одну и ту же функцию. Обратите внимание на одноразовое использование и положение &. Таким образом, & является здесь ссылочным оператором, а не оператором адресации. Чтобы вызвать функцию, просто используйте любое имя.

Идентификатор ссылки — это не то же самое, что идентификатор указателя.

Функция, возвращающая указатель

В следующей программе функция возвращает указатель, который является адресом указанного объекта:

Первый оператор в функции fn () предназначен только для создания объекта-указателя. Обратите внимание на одноразовое использование и положение * в сигнатуре функции. Также обратите внимание, как указатель (адрес) был получен в функции main () другим объектом-указателем.

Функция, возвращающая ссылку

В следующей программе функция возвращает ссылку:

Первый оператор в функции fn () предназначен только для создания ссылки. Обратите внимание на одноразовое использование и положение & в сигнатуре функции. Также обратите внимание, как ссылка была получена в функции main () по другой ссылке.

Передача указателя на функцию

В следующей программе указатель, который на самом деле является адресом объекта с плавающей точкой, отправляется в качестве аргумента функции:

int main ( )
<
float v = 2.5 ;

Обратите внимание на использование и положение * для параметра с плавающей запятой в сигнатуре функции. Как только начинается вычисление функции fn (), делается следующий оператор:

Передача ссылки на функцию

В следующей программе ссылка отправляется в качестве аргумента функции:

int main ( )
<
float v = 2.5 ;

Обратите внимание на использование и положение & для параметра float в сигнатуре функции. Как только начинается вычисление функции fn (), делается следующий оператор:

Передача массива функции

Следующая программа показывает, как передать массив функции:

int fn ( int arra [ ] )
<
return arra [ 2 ] ;
>

В этой программе передается массив. Обратите внимание, что параметр сигнатуры функции имеет объявление пустого массива. Аргументом в вызове функции является только имя созданного массива.

Может ли функция C ++ вернуть массив?

Функция в C ++ может возвращать значение массива, но не может возвращать массив. Компиляция следующей программы приводит к сообщению об ошибке:

int fn ( int arra [ ] )
<
return arra ;
>

Указатель указателя

Указатель может указывать на другой указатель. То есть объект-указатель может иметь адрес другого объекта-указателя. Они по-прежнему должны быть одного типа. Следующий фрагмент кода иллюстрирует это:

В объявлении указателя на указатель используется двойной *. Чтобы вернуть значение последнего заостренного объекта, по-прежнему используется двойной *.

Массив указателей

Следующая программа показывает, как кодировать массив указателей:

Обратите внимание на использование и положение * в объявлении массива. Обратите внимание на использование * при возврате значения в массиве. С указателями указателей задействованы два *. В случае массива указателей об одном * уже позаботились, потому что идентификатор массива является указателем.

Массив строк переменной длины

Строковый литерал — это константа, возвращающая указатель. Массив строк переменной длины — это массив указателей. Каждое значение в массиве является указателем. Указатели — это адреса к ячейкам памяти, они имеют одинаковый размер. Строки разной длины находятся в другом месте памяти, а не в массиве. Следующая программа иллюстрирует использование:

На выходе получается «girl».

Объявление массива начинается с зарезервированного слова «const» для константы; за которым следует «char» для символа, затем звездочка *, чтобы указать, что каждый элемент является указателем. Чтобы вернуть строку из массива, * не используется из-за неявного характера указателя каждой строки. Если используется *, то будет возвращен первый элемент строки.

Указатель на функцию, возвращающую указатель

Следующая программа показывает, как кодируется указатель на функцию, возвращающую указатель:

int * fn ( )
<
int num = 4 ;
int * inter = & num ;
return inter ;
>

int * ( * func ) ( ) = & fn ;
int val = * func ( ) ;

Объявление указателя на функцию, возвращающую указатель, аналогично объявлению указателя на обычную функцию, но перед ним стоит звездочка. Первый оператор в функции main () иллюстрирует это. Чтобы вызвать функцию с помощью указателя, поставьте перед ней *.

Заключение

Чтобы создать указатель на скаляр, сделайте что-нибудь вроде:

* имеет два значения: в объявлении указывает указатель; чтобы что-то вернуть, это значение указанного объекта.

Имя массива — это постоянный указатель на первый элемент массива.

Чтобы создать указатель на функцию, вы можете:

где fn () — функция, определенная в другом месте, а func — указатель.

Чтобы создать ссылку на функцию, вы можете:

где fn () — функция, определенная в другом месте, а refFunc — ссылка.

Когда функция возвращает указатель, возвращаемое значение должно быть получено указателем. Когда функция возвращает ссылку, возвращаемое значение должно быть получено по ссылке.

При передаче указателя на функцию параметр является объявлением, а аргумент — адресом указанного объекта. При передаче ссылки на функцию параметр является объявлением, а аргумент — ссылкой.

При передаче массива функции параметр — это объявление, а аргумент — это имя массива без []. Функция C ++ не возвращает массив.

Для указателя на указатель требуется два * вместо одного, где это необходимо.

Источник

Указатели, ссылки и массивы в C и C++: точки над i

В этом посте я постараюсь окончательно разобрать такие тонкие понятия в C и C++, как указатели, ссылки и массивы. В частности, я отвечу на вопрос, так являются массивы C указателями или нет.

Обозначения и предположения

Указатели и ссылки

Указатели. Что такое указатели, я рассказывать не буду. 🙂 Будем считать, что вы это знаете. Напомню лишь следующие вещи (все примеры кода предполагаются находящимися внутри какой-нибудь функции, например, main):

Ссылки. Теперь по поводу ссылок. Ссылки — это то же самое, что и указатели, но с другим синтаксисом и некоторыми другими важными отличиями, о которых речь пойдёт дальше. Следующий код ничем не отличается от предыдущего, за исключением того, что в нём фигурируют ссылки вместо указателей:

Если слева от знака присваивания стоит ссылка, то нет никакого способа понять, хотим мы присвоить самой ссылке или объекту, на который она ссылается. Поэтому такое присваивание всегда присваивает объекту, а не ссылке. Но это не относится к инициализации ссылки: инициализируется, разумеется, сама ссылка. Поэтому после инициализации ссылки нет никакого способа изменить её саму, т. е. ссылка всегда постоянна (но не её объект).

Удивительный факт состоит в том, что ссылки и lvalue — это в каком-то смысле одно и то же. Давайте порассуждаем. Что такое lvalue? Это нечто, чему можно присвоить. Т. е. это некое фиксированное место в памяти, куда можно что-то положить. Т. е. адрес. Т. е. указатель или ссылка (как мы уже знаем, указатели и ссылки — это два синтаксически разных способа в C++ выразить понятие адреса). Причём скорее ссылка, чем указатель, т. к. ссылку можно поместить слева от знака равенства и это будет означать присваивание объекту, на который указывает ссылка. Значит, lvalue — это ссылка.

А что такое ссылка? Это один из синтаксисов для адреса, т. е., опять-таки, чего-то, куда можно класть. И ссылку можно ставить слева от знака равенства. Значит, ссылка — это lvalue.

Окей, но ведь (почти любая) переменная тоже может быть слева от знака равенства. Значит, (такая) переменная — ссылка? Почти. Выражение, представляющее собой переменную — ссылка.

Этот принцип («выражение, являющееся переменной — ссылка») — моя выдумка. Т. е. ни в каком учебнике, стандарте и т. д. я этот принцип не видел. Тем не менее, он многое упрощает и его удобно считать верным. Если бы я реализовывал компилятор, я бы просто считал там переменные в выражениях ссылками, и, вполне возможно, именно так и предполагается в реальных компиляторах.

Более того, удобно считать, что особый тип данных для lvalue (т. е. ссылка) существует даже и в C. Именно так мы и будет дальше предполагать. Просто понятие ссылки нельзя выразить синтаксически в C, ссылку нельзя объявить.

Принцип «любое lvalue — ссылка» — тоже моя выдумка. А вот принцип «любая ссылка — lvalue» — вполне законный, общепризнанный принцип (разумеется, ссылка должна быть ссылкой на изменяемый объект, и этот объект должен допускать присваивание).

Операции * и &. Наши соглашения позволяют по-новому взглянуть на операции * и &. Теперь становится понятно следующее: операция * может применяться только к указателю (конкретно это было всегда известно) и она возвращает ссылку на тот же тип. & применяется всегда к ссылке и возвращает указатель того же типа. Таким образом, * и & превращают указатели и ссылки друг в друга. Т. е. по сути они вообще ничего не делают и лишь заменяют сущности одного синтаксиса на сущности другого! Таким образом, & вообще-то не совсем правильно называть операцией взятия адреса: она может быть применена лишь к уже существующему адресу, просто она меняет синтаксическое воплощение этого адреса.

Также замечу, что &*EXPR (здесь EXPR — это произвольное выражение, не обязательно один идентификатор) эквивалентно EXPR всегда, когда имеет смысл (т. е. всегда, когда EXPR — указатель), а *&EXPR тоже эквивалентно EXPR всегда, когда имеет смысл (т. е. когда EXPR — ссылка).

Массивы

Итак, есть такой тип данных — массив. Определяются массивы, например, так:

Выражение в квадратных скобках должно быть непременно константой времени компиляции в C89 и C++98. При этом в квадратных скобках должно стоять число, пустые квадратные скобки не допускаются.

то, опять-таки, место для массива будет целиком выделяться прямо внутри структуры, и sizeof от этой структуры будет это подтверждать.

Хорошо, будем считать, я вас убедил, что массив — это именно массив, а не что-нибудь ещё. Откуда тогда берётся вся эта путаница между указателями и массивами? Дело в том, что имя массива почти при любых операциях преобразуется в указатель на его нулевой элемент.

Конвертирование имени массива в void * или применение к нему == тоже приводит к предварительному преобразованию этого имени в указатель на первый элемент, поэтому:

Типы у участвовавших выражений следующие:

Массив нельзя передать как аргумент в функцию. Если вы напишите int x[2] или int x[] в заголовке функции, то это будет эквивалентно int *x и в функцию всегда будет передаваться указатель (sizeof от переданной переменной будет таким, как у указателя). При этом размер массива, указанный в заголовке будет игнорироваться. Вы запросто можете указать в заголовке int x[2] и передать туда массив длины 3.

Однако, в C++ существует способ передать в функцию ссылку на массив:

При такой передаче вы всё равно передаёте лишь ссылку, а не массив, т. е. массив не копируется. Но всё же вы получаете несколько отличий по сравнению с обычной передачей указателя. Передаётся ссылка на массив. Вместо неё нельзя передать указатель. Нужно передать именно массив указанного размера. Внутри функции ссылка на массив будет вести себя именно как ссылка на массив, например, у неё будет sizeof как у массива.

И что самое интересное, эту передачу можно использовать так:

Похожим образом реализована функция std::end в C++11 для массивов.

«Указатель на массив». Строго говоря, «указатель на массив» — это именно указатель на массив и ничто другое. Иными словами:

Однако, иногда под фразой «указатель на массив» неформально понимают указатель на область памяти, в которой размещён массив, даже если тип у этого указателя неподходящий. В соответствии с таким неформальным пониманием c и d (и b + 0 ) — это указатели на массивы.

А теперь посмотрим на такую ситуацию:

Источник

Указатели

Что такое указатели

Указатели представляют собой объекты, значением которых служат адреса других объектов (переменных, констант, указателей) или функций. Как и ссылки, указатели применяются для косвенного доступа к объекту. Однако в отличие от ссылок указатели обладают большими возможностями.

Для определения указателя надо указать тип объекта, на который указывает указатель, и символ звездочки *. Например, определим указатель на объект типа int:

Пока указатель не ссылается ни на какой объект. При этом в отличие от ссылки указатель необязательно инициализировать каким-либо значением. Теперь присвоим указателю адрес переменной:

Если мы попробуем вывести адрес переменной на консоль, то увидим, что он представляет шестнадцатиричное значение:

Консольный вывод программы:

Для чего нужны указатели в программировании. Смотреть фото Для чего нужны указатели в программировании. Смотреть картинку Для чего нужны указатели в программировании. Картинка про Для чего нужны указатели в программировании. Фото Для чего нужны указатели в программировании

И указатель p будет ссылаться на адрес, по которому располагается переменная x, то есть на адрес 0x60FE98.

Но так как указатель хранит адрес, то мы можем по этому адресу получить хранящееся там значение, то есть значение переменной x. Для этого применяется операция * или операция разыменования, то есть та операция, которая применяется при определении указателя. Результатом этой операции всегда является объект, на который указывает указатель. Применим данную операцию и получим значение переменной x:

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

И также используя указатель, мы можем менять значение по адресу, который хранится в указателе:

Так как по адресу, на который указывает указатель, располагается переменная x, то соответственно ее значение изменится.

Создадим еще несколько указателей:

В моем случае я получу следующий консольный вывод:

По адресам можно увидеть, что переменные часто расположены в памяти рядом, но не обязательно в том порядке, в котором они определены в коде программы:

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *