В C можно ли найти нелокальные переменные функций и процедур в куче и статической зоне? в куче те, которые распределяются динамически, т. е. с использованием malloc и calloc. Однако в статической области есть глобальные переменные, доступные из всех точек программы, верно? вместо этого в стеке находятся локальные переменные функций или процедур, верно?
Однако в статической области есть глобальные переменные, доступные из всех точек программы, верно? Нет, если переменная static
определена локально. Тогда его область действия ограничивается функцией. А если «глобальная» переменная равна static
, то ее область действия ограничена этим файлом, а не «со всех точек программы».
Он хранится в сегменте данных X86 , ARM и т. д.
Объяснение видеолекций с сегментацией памяти
Итак, в C нелокальные переменные функции и процедуры находятся в статической зоне?
C язык не знает ни стека, ни кучи. Это детали реализации.
@WeatherVane: все объекты доступны в программе C в течение их жизни. «Доступ» означает чтение или запись объекта, и вы можете сделать это, если у вас есть его адрес (кроме записи объекта const
, конечно). Область действия имени отличается от доступа к объекту.
В C нет «функций и процедур», есть только функции. Поэтому он несколько отличается от таких языков, как Pascal или Basic.
Внешнее объяснение: Что выделяется в стеке и куче?
Когда объекты хранятся реализациями C, это сложно; это определяется не только тем, является ли переменная «локальной» или нет. Две переменные, определенные внутри функции, с одинаковой областью действия их имен, могут храниться в разных местах, поскольку одна из них объявлена с помощью static
, а другая — нет.
Стандарт C не определяет никакие переменные как «локальные» или «глобальные». Он даже не использует эти слова для описания переменных, за исключением одного проходного экземпляра, связанного с именами параметров main
. А в стандарте вообще не используется слово «процедура».
В C переменная состоит из двух частей: идентификатора (имени) и памяти, которая используется для переменной. Память называется объектом.
Независимо от того, где объявлена переменная или как создан объект, объект доступен во всей программе в течение всего времени его существования. В стандарте C «доступ» означает чтение или запись объекта, и любая часть программы может читать или записывать объект, если у нее есть адрес объекта (за исключением того, что запись в объект, определенный с помощью const
, не определена).
Если вас беспокоят «локальные» и «глобальные» переменные, вас, скорее всего, действительно беспокоит область действия идентификатора. Область — это область исходного кода программы, где идентификатор может использоваться для ссылки на связанный с ним объект (кроме случаев, когда он скрыт другим объявлением того же идентификатора во внутренней области).
В обычных реализациях C общего назначения время хранения объекта определяется длительностью его хранения. C имеет четыре продолжительности хранения:
Автоматическая продолжительность хранения: параметр функции или объект, объявленный внутри функции без static
, имеет автоматическую продолжительность хранения. Эти объекты хранятся в стеке или, благодаря оптимизации, удерживаются в регистрах или оптимизируются (а иногда и смешанно, включая нахождение в разных регистрах или местах стека в разное время).
Продолжительность хранения потока: объект, объявленный с помощью _Thread_local
, имеет продолжительность хранения потока. Мне не приходилось беспокоиться о том, где они хранятся, но я предполагаю, что они находятся в памяти, выделяемой при создании потока.
Статическая продолжительность хранения: объект, объявленный без _Thread_local
и вне функции, или внутри функции с static
, имеет статическую продолжительность хранения. Вы можете думать, что они хранятся в так называемой «статической зоне». Однако для них может быть несколько разделов программы. Примечательно, что статические объекты, которые должны быть инициализированы нулевым значением, могут храниться в разделе программы специально для этой цели, тогда как статические объекты с ненулевыми начальными значениями могут храниться в другом разделе программы. Раздел, заполненный нулями, инициализируется операционной системой, когда для него выделяется память, поэтому он занимает мало места в исполняемом файле программы. Незаполненная нулями секция инициализируется путем чтения данных из исполняемого файла программы в память.
Выделенная продолжительность хранения: объект, созданный вызовами функций управления памятью, таких как malloc
и free
, имеет выделенную продолжительность хранения. Используемая для этого память называется кучей, хотя по историческим причинам это неправильное название.
Вышеуказанное является общей схемой, используемой для реализаций C, но стандарт C допускает другие реализации.
Обратите внимание, что «локальный» может быть подходящим описанием идентификаторов с областью действия блока, но «глобальный» не совсем корректен для любых идентификаторов в C, кроме ключевых слов. C имеет идентификаторы с областью действия файла (имя известно во всей единице перевода с момента объявления) и внешней связью (разные объявления имени в разных единицах перевода могут быть связаны с одним и тем же объектом), но не имеет каких-либо глобальных идентификаторов. . Чтобы идентификатор был по-настоящему глобальным, его объявление один раз в программе должно сделать его известным во всей программе. В C этого нет; Чтобы использовать идентификатор в нескольких единицах перевода, его необходимо объявлять отдельно в каждой единице.
Итак, в C нелокальные переменные процедуры и функции находятся только в статической зоне?
@dok: Если переменная определена вне какой-либо функции и не является _Thread_local
, она должна иметь статическую продолжительность хранения, поэтому она будет храниться в месте, где хранятся объекты со статической продолжительностью хранения.
Языки C говорят, что если переменная является локальной по отношению к блоку (будь то функция или нет), ее время жизни заканчивается в конце блока. Распространенный способ — использовать для этого стек, потому что вам просто нужно извлечь переменную из стека в конце блока, где она объявлена. Но реализация может решить хранить в стеке только простые переменные и адреса и использовать статическую зону или кучу для массивов, если в конкретной системе размер стека должен быть минимальным. При условии, что наблюдаемые результаты программы одинаковы, реализация может делать что угодно.
Локальную переменную
static
не удалось сохранить в стеке.