Как определяется память в стеке, если в ней нет указателей?

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

Я читал книгу Head First C, в которой говорилось об указателях. Было ли это просто ссылкой на указатели в качестве примера? Или в памяти в стеке есть какой-то указатель на память?

Если нет, то как это определить? Путаница или противоречие между публикациями в Интернете и книгами действительно сбили меня с толку по предмету, который я только сейчас понимаю. Кто-нибудь может это прояснить?

Похоже, вы неправильно поняли то, что говорилось в книге. Утверждение, которое вы приписываете книге, не имеет смысла.

user2357112 supports Monica 02.05.2018 07:18

Указатель - это просто переменная, которая хранит адрес чего-то еще в качестве своего значения. Если вы обычно думаете о переменной, содержащей немедленные значения, например int a = 5;, указатель будет просто содержать адрес, по которому хранится 5, например int *b = &a;. Другими словами, bточки, где хранится значение a (например, от bточки до a).

David C. Rankin 02.05.2018 07:18

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

Jean-Baptiste Yunès 02.05.2018 07:19

Итак, как стек, так и куча имеют указатели на свои значения или указатели на их слоты памяти, или если char* указывает на первый элемент этого массива? Или это всего лишь куча.

chaotic 02.05.2018 07:20

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

David C. Rankin 02.05.2018 07:23

У каждого объекта есть размер, и он складывает все, подождите, уложите один поверх другого. Вы продвигаетесь вверх и выскакиваете вниз. Никаких идентификаторов не требуется, вам просто нужно знать, сколько вещей надеть, а затем сколько снять, когда они выйдут за рамки. Компилятор позаботится об этом за вас.

user4581301 02.05.2018 07:24

Может помочь опубликовать точный текст из книги

M.M 02.05.2018 07:32

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

Leonard 02.05.2018 07:37

По моему опыту, книги «Сначала голова» ужасны.

molbdnilo 02.05.2018 08:20

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

Mark Setchell 02.05.2018 08:20

Я предполагаю, что книга хочет сказать вам, что вы можете получить доступ к памяти в стеке без использования указателей. Вы можете просто использовать int var; и более поздние версии var = 123; в своей функции, и вам не нужно беспокоиться об указателях. Доступ к памяти в куче невозможен без явного использования указателей.

Gerhardh 02.05.2018 09:05

@MarkSetchell: Вы думаете о x86. Это не универсально. У SPARC был регистровый файл.

MSalters 02.05.2018 10:46

@MSalters, если ваша программа на C принимает адрес локального, компилятор SPARC должен поместить этот локальный адрес куда-нибудь

Caleth 02.05.2018 10:53

@Caleth: На самом деле, вы можете быть удивлены тем, насколько хорошими могут быть компиляторы. Например, если вы просто укажете адрес printf, вы можете обнаружить, что компилятор никогда не потрудится пролить регистр. Правило «AS-IF» довольно мощное.

MSalters 02.05.2018 10:57

@MSalters Ок, "берет и использует нетривиальным образом адрес локального".

Caleth 02.05.2018 11:03
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
15
122
2

Ответы 2

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

Значение указателя - это адрес ячейки памяти, а переменная-указатель - это переменная, которая может хранить значение указателя.

В C почти все имеет адрес. Исключение составляют временные значения и объекты, объявленные как register.

melpomene 02.05.2018 07:35

На данные в стеке ссылаются по смещению от указателя стека / базы.

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

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

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

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

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

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

MSalters 02.05.2018 11:00

Может быть, я неправильно * понимаю вас, не могли бы вы подробнее рассказать, как стек может быть связанным списком?

Jay Wai Tan 03.05.2018 17:25

Другие вопросы по теме