Подтвердить что ты не робот

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

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

4b9b3361

Ответ 1

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

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

Ответ 2

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

  1. Сегмент кода - хранит только код, ПЗУ
  2. BSS (или блок, начатый символом) Сегмент данных - хранит инициализированные глобальные и статические переменные
  3. Сегмент стека - хранит все локальные переменные и другую информацию, касающуюся адреса возврата функции и т.д.
  4. Сегмент кучи - все динамические выделения происходят здесь
  5. Сегмент BSS данных (или блок, начатый символом) - хранит неинициализированные глобальные и статические переменные

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

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

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

Например:

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

Подводя итог, можно сказать, что "const" - это просто КВАЛИФЕР данных, что означает, что сначала компилятор должен решить, в каком сегменте должна быть сохранена переменная, а затем, если переменная является константой, то она может быть сохранена в защищенной от записи области этот конкретный сегмент.

Ответ 3

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

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 должны иметь более длинные и более значимые имена, это только пример!)

Ответ 4

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

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

Ответ 5

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

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 байт и большие средствa > 8 байтов и равные значения.

но мое сомнение - это локальная константа, где он будет работать??????

Ответ 6

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

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

Ответ 7

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

Ответ 8

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

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

Ответ 9

Некоторые константы arfen't даже сохранены.

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

Ответ 10

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

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

#import<math.h>//import PI
double toRadian(int degree){
  return degree*PI*2/360.0;
}

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

Ответ 11

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

Ответ 13

Я проверил в системе x86_64 GNU/Linux. Используя указатель на переменную 'const', значение можно изменить. Я использовал objdump. Не удалось найти переменную const в текстовом сегменте. Переменная const хранится в стеке.