Где постоянные переменные хранятся в C?

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

Как они хранятся, это деталь реализации (зависит от компилятора).

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

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

  1. Сегмент кода – хранит только код, ROM
  2. Сегмент BSS (или Block Started by Symbols) – Сохраняет инициализированные глобальные и статические переменные
  3. Сегмент стека – сохраняет все локальные varialbles и другую информацию о возврате адреса функции и т. Д.
  4. Сегмент кучи – все динамические распределения происходят здесь
  5. Сегмент данных – хранит неинициализированные глобальные и статические переменные

Обратите внимание, что разница между сегментом BSS и данными заключается в том, что прежние хранилища инициализировали глобальные и статические varialbes, а более поздние – UNinitialised.

Теперь, почему я говорю о сегментации данных, когда я должен просто говорить, где хранятся постоянные переменные … есть причина для этого …

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

Например,

если у меня есть константа int, которая является локальной переменной, то она сохраняется в области, защищенной от записи сегмента стека. и если у меня есть глобальный, который инициализируется const var, то он сохраняется в BSS, и если у меня есть uninitialised const var, то он сохраняется в сегменте данных …

Подводя итог, «const» – это просто QUALIFIER данных, что означает, что сначала компилятор должен решить, какой сегмент должен быть сохранен, а затем, если переменная является константой, тогда она может быть сохранена в защищенной от записи области этот конкретный сегмент.

Надеюсь, это разъяснит большую часть недоразумений …. 🙂

Любые дальнейшие комментарии приветствуются … 🙂

Рассмотрим код:

const int i = 0; static const int k = 99; int function(void) { const int j = 37; totherfunc(&j); totherfunc(&i); //totherfunc(&k); return(j+3); } 

Как правило, i могу быть сохранен в текстовом сегменте (это переменная только для чтения с фиксированным значением). Если он не находится в текстовом сегменте, он будет храниться рядом с глобальными переменными. Учитывая, что он инициализирован нулем, он может находиться в разделе «bss» (где обычно назначаются нулевые переменные) или в разделе «данные» (где обычно назначаются инициализированные переменные).

Если компилятор убежден, что k не используется (что может быть, так как оно является локальным для одного файла), оно может вообще не отображаться в объектном коде. Если вызов totherfunc() который ссылается на k не был прокомментирован, тогда k должен быть назначен адрес где-то – он, вероятно, будет в том же сегменте, что i .

Константа (если она является константой, является ли она по-прежнему переменной?) j скорее всего появится в стеке обычной реализации C. (Если вы спрашивали в группе новостей comp.std.c, кто-то упомянул бы, что стандарт не говорит о том, что в стеке появляются автоматические переменные, к счастью, SO не является comp.std.c!)

Обратите внимание, что я заставил переменные отображаться, потому что я передал их по ссылке – предположительно к функции, ожидающей указателя на постоянное целое число. Если адреса не были приняты, то j и k могут быть полностью исключены из кода. Чтобы удалить i , компилятор должен знать весь исходный код для всей программы – он доступен в других единицах перевода (исходные файлы) и поэтому не может быть легко удален. Совсем не так, если программа потакает динамической загрузке разделяемых библиотек – одна из этих библиотек может опираться на эту глобальную переменную.

(Стилистически – переменные i и j должны иметь более длинные, более значимые имена, это только пример!)

Зависит от вашего компилятора, ваших системных возможностей, конфигурации при компиляции.

gcc помещает константы только для чтения в раздел .text , если не указано иное.

Обычно они хранятся в разделе данных только для чтения (в то время как в разделе глобальных переменных есть разрешения на запись). Таким образом, попытка изменить константу, взяв ее адрес, может привести к нарушению доступа aka segfault.

Но это зависит от вашего оборудования, ОС и компилятора.

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

offcourse нет, потому что

1) сегмент bss хранит неинициализированные переменные, очевидно, что существует другой тип.

  (I) large static and global and non constants and non initilaized variables it stored .BSS section. (II) second thing small static and global variables and non constants and non initilaized variables stored in .SBSS section this included in .BSS segment. 

2) сегмент данных – это инициализированные переменные, он имеет 3 типа,

  (I) large static and global and initlaized and non constants variables its stord in .DATA section. (II) small static and global and non constant and initilaized variables its stord in .SDATA1 sectiion. (III) small static and global and constant and initilaized OR non initilaized variables its stord in .SDATA2 sectiion. 

я упоминаю выше, малые и большие средства откладываются на complier, например, малые средства <8 байт и большие средства> 8 байтов и равные значения.

но я сомневаюсь, что локальная константа – это то, где она будет двигаться ??????

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

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

Некоторые константы даже не хранятся.

Рассмотрим следующий код: int x = foo(); x *= 2; int x = foo(); x *= 2; , Скорее всего, компилятор превратит умножение в x = x+x; так как это уменьшает необходимость загрузки номера 2 из памяти.

Он может вообще не храниться.

Рассмотрим такой код:

 #import//import PI double toRadian(int degree){ return degree*PI*2/360.0; } 

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

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

Он должен храниться в сегменте Text, так как он доступен только для чтения. http://shirleyanengineer.blogspot.in/2017/05/memory-layout-of-process.html

  • Как динамически распределять пространство памяти для строки и получать эту строку от пользователя?
  • Как работают realloc и memcpy?
  • Как я могу получить размер массива из указателя в C?
  • Эффективные C ++ строки (интернирование, веревки, копирование на запись и т. Д.)
  • Как инициализировать память новым оператором в C ++?
  • Методы classа, которые создают новые экземпляры
  • Размещение массива-new требует неопределенных накладных расходов в буфере?
  • Безопасно ли удалять указатель на пустоту?
  • Удаляет ли вызов деструктор?
  • Почему моя программа работает медленнее, если вы перебираете ровно 8192 элементов?
  • Можно ли удалить не новый объект?
  • Давайте будем гением компьютера.