Классы памяти в си: Классы памяти в языке Си

Классы памяти в C++ Builder × C++ Builder программирование

Каждая переменная характеризуется некоторым классом памяти, который определяет ее время жизни, в течение которого эта переменная существует в памяти. Одни переменные существуют недолго, другие неоднократно создаются и уничтожаются, третьи существуют на протяжении всего времени выполнения программы. В C++Builder имеется четыре спецификации класса памяти: auto, register, extern и static. Спецификация класса памяти идентификатора определяет erq класс памяти, область действия и пространство имен. Областью действия (областью видимости) идентификатора называется область программы, в которой на данную переменную (как, впрочем, и на любой идентификатор — константу, функцию и т.п.) можно сослаться. На некоторые переменные можно сослаться в любом месте программы, тогда как на другие только в определенных ее частях.

Класс памяти определяется, в частности, местом объявления переменной.

Локальные переменные объявляются внутри некоторого блока или функции. Эти переменные видны только в пределах того блока, в котором они объявлены. Блоком называется фрагмент кода, ограниченный фигурными скобками «{ }». Глобальные переменные объявляются вне какого-либо блока или функции.

Спецификации класса памяти могут быть разбиты на два класса: автоматический класс памяти с локальным временем жизни и статический класс памяти с глобальным временем жизни. Ключевые слова auto и register используются для объявления переменных с локальным временем жизни. Эти спецификации применимы только к локальным переменным. Локальные переменные создаются при входе в блок, в котором они объявлены, существуют лишь во время активности блока и исчезают при выходе из блока.

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

auto float x, у;

Локальные переменные являются переменными с локальным временем жизни по умолчанию, так что ключевое слово

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

{
int i = 1;
...
i++;
...
}

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

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

register int i = 1;

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

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

register используется редко.

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

Существует два типа переменных статического класса памяти: глобальные переменные и локальные переменные, объявленные спецификацией класса памяти static. Глобальные переменные по умолчанию относятся к классу памяти extern. Глобальные переменные создаются путем размещения их объявлений вне описания какой-либо функции и сохраняют свои значения в течение всего времени выполнения программы. На глобальные переменные может ссылаться любая функция, которая расположена после их объявления или описания в файле.

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

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

Вернемся к уже рассмотренному выше примеру, но укажем для переменной i статический класс:

{
static int i = 1;
.
.. i++; ... }

Инициализация переменной i произойдет только один раз за время выполнения программы. При первом обращении к этому блоку значение переменной i будет равно 1. К концу выполнения блока ее значение станет равно 2. При следующем обращении к блоку это значение сохранится и при окончании повторного выполнения блока i будет равно 3. Таким образом, статическая переменная способна хранить информацию между обращениями к блаку и, следовательно, может использоваться, например, как счетчик числа обращений.

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

Спецификации класса памяти extern используются в программах с несколькими файлами. Пусть, например, в модуле

Unit1 в файле Unit1.cpp или Unit1.h (это безразлично) объявлена глобальная переменная:

int а = 5;

Тогда, если в другом модуле Unit2 в файле Unit2. cpp или Unit2.h объявлена глобальная переменная:

extern int а;

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

Поделиться


c++ — Где в памяти располагаются функции-поля классов?

Разбирался с классами и стало интересно,как и где хранятся функции-поля классов. Если получить размер класса,то размер будет равен сумме размеров всех нестатических полей + выравнивание. Не совсем понимаю,где тогда размещаются функции классов и их статические поля.Или для каждого класса будет своя функция или для всех классов используется 1 функция-поле класса?

Так же пытался найти адрес функций,но не получилось:

class myclass {
 public:
    int a;
    float b;
    static int c;
    int func1() { a = 4; return a; };
    int func2() { a = 6; return a;};
};
int myclass::c;
int main()
{
    myclass a1;
    cout <<sizeof(myclass)<< endl; //8 байт
    cout<<"addr class: "<< &a1 <<endl;         //67C5DDF7A0
    cout << "addr a class: " << &a1. a << endl; //67C5DDF7A0
    cout << "addr b class: " << &a1.b << endl; //67C5DDF7A4
    cout << "addr b class: " << &a1.c << endl; //7FF6866996A0
    cout << "addr func1 class: " << &myclass::a << endl;     //1 (Что мы получаем?)
    cout << "addr func1 class: " << &myclass::func1 << endl; //1 (Что это?)
    cout << "addr func2 class: " << &myclass::func2 << endl; //1
    cout << "addr func1 class: " << &a1.func1 << endl; //ошибка компиляции (Интересно почему?)
    cout << "addr func2 class: " << &a1.func2 << endl; //ошибка компиляции
}
  • c++
  • функции
  • классы
  • объекты
  • адрес
16

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

Если это виртуальные функции — то их адреса хранятся в таблице виртуальных функций и опять же эта таблица одна на класс, так что в каждый объект добавляется только указатель на нее.

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

Зарегистрируйтесь или войдите

Регистрация через Google

Регистрация через Facebook

Регистрация через почту

Отправить без регистрации

Почта

Необходима, но никому не показывается

Отправить без регистрации

Почта

Необходима, но никому не показывается

By clicking “Отправить ответ”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

классов хранения в C | Классы памяти C

Обзор

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

Что такое класс хранения в C?

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

Эти два свойства многое говорят о переменной, например, тип данных говорит о размере и двоичном представлении переменной в памяти.

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

Что касается класса Storage, он определяет следующие атрибуты переменной:

1. Область действия (видимость переменной):

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

2. Значение определения по умолчанию:

Выделение памяти не происходит в объявлении, тогда как в определении память выделяется для переменной.

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

Значение определения переменной по умолчанию по умолчанию зависит от класса хранения переменной. Это может быть случайное значение или ноль зависит от класса хранения.

3. Время жизни:

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

Синтаксис

Для определения класса хранения переменной необходимо использовать следующий синтаксис:

Структура памяти программы C

Типичная архитектура памяти программы C может быть разбита на 4 части:

1. Сегмент кода:

Он состоит из исполняемых инструкций программы и выделяется фиксированного размера в соответствии с длиной инструкций во время компиляции программы. Например, простой код печати «Hello world» хранится внутри сегмента кода.

2. Статические и глобальные переменные:

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

3. Стек:

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

4. Куча:

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

Сводка по классам памяти в C

Давайте теперь подведем итоги по классам памяти в C:

Класс хранения Объем Срок службы Исходное значение Место хранения
Авто Внутри блока, в котором он объявлен. Внутри блока, в котором он объявлен. Инициализирован со значением мусора. RAM
Регистр Внутри блока, в котором он определен. То же, что и auto, в блоке, в котором он объявлен. Инициализирован со значением мусора. Регистр
Статический Внутри блока, в котором он определен. На протяжении всей основной программы. Ноль. RAM
Extern Глобальная область действия, не связанная какой-либо функцией. То же, что и статическое, до конца основной программы. Ноль. ОЗУ

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

Давайте посмотрим на использование памяти класса C:

  • Помогает определить область действия, видимость, время жизни переменной.
  • Мы можем использовать более одной переменной с одним и тем же именем.

Типы класса хранения в C

1. Класс автоматического хранения в C:

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

Синтаксис для определения автоматической переменной:

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

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

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

2. Класс хранения регистров в C:

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

  • Локальная область действия
  • Случайное начальное значение (мусорное значение)
  • Время жизни до конца блока

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

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

Синтаксис для определения регистровой переменной:

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

3. Статический класс хранения в C:

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

После определения статической переменной она сохраняется до конца программы.

Статические переменные в C по умолчанию инициализируются «0», и их область действия ограничена родительским блоком, который является локальными статическими переменными.

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

Вывод:

Здесь out — это глобальная статическая переменная со значением по умолчанию 0, а in — это локальная статическая переменная, область действия которой ограничена только основной функцией, но время жизни — до конца программы, что является общим для как глобальные, так и локальные статические.

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

Вывод:

В приведенном выше коде sVar является локальной статической переменной и инициализируется нулем в статической памяти, поскольку функция incstatic вызывается в первый раз в основной функции.

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

4. Класс внешнего хранилища в C и ключевое слово extern:

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

Вывод:

Здесь gVar — это глобальная переменная, инициализированная «0» по умолчанию и доступная во всей программе и даже в других файлах через компоновщик.

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

Ключевое слово Extern:

Ключевое слово extern используется для объявления глобальной переменной, мы узнали выше, что объявление против определения, что в объявлении память не выделяется для переменной, которую мы объявляем, это просто ссылка на компилятор, который определение переменной находится где-то в программе или в другом файле.

В приведенном выше коде мы использовали extern для объявления переменной max в main() , которая указывает компилятору использовать max , не беспокоясь о его определении, которое будет исправлено во время компоновки из той же программы или другой. Во время выполнения max можно использовать в основной функции с помощью extern, и его значение будет изменено на 5, а 5 будет напечатано на экране.

Если вы удалите весь оператор объявления extern extern in max ; из приведенного выше кода он выдаст эту ошибку компиляции, ‘max’ необъявленный (первое использование в этой функции).

Программа вообще не будет скомпилирована, так как компилятор не видел никакого определения для max до его использования. Следовательно, extern используется для объявления глобальных переменных, чтобы наша программа была успешно скомпилирована, а определения будут связаны во время компоновки с объявлениями extern.

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

Преимущества и недостатки класса хранения C

Давайте рассмотрим преимущества класса хранения C:

  • Помогает определить область действия, видимость, время жизни переменной.
  • Мы можем использовать более одной переменной с одним и тем же именем.

Некоторые недостатки хранилища класса C:

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

900 86 До конца программы
Отличия Auto Static
Синтаксис объявления auto int a = 5; статический интервал a = 5;
Объем Внутренний блок Внутри блока
Начальное значение Мусор Ноль
Время жизни До конца блока

Резюме

Подводя итог, Классы памяти играют решающую роль в управлении памятью программы на C. Отныне используйте классы хранения в программе C и получайте доступ к памяти программы. Не позволяйте компилятору запугивать вас 🙂

9 0086 Автоматический
Класс хранения Хранилище Начальное значение по умолчанию Объем Срок службы
Стек Мусор локальный внутри блока конец блока
Регистр Стек или регистр ЦП Мусор Локальный внутри блока Конец блока
Статический Статическая память 0 Локальная или глобальная, внутри блока или внутри файла Конец программы
Внешняя Статическая память 0 Общий Конец программы

Следует иметь в виду, что глобальные и статические переменные хранятся в статической памяти, а локальные переменные — в стеке функции.

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

Классы хранения в C – Блог MVPS.net

Класс хранения (память) показывает, когда, как и где выделяется память для переменной (вектор). Любая переменная C имеет класс памяти, который вытекает либо из явного оператора, либо неявно из того места, где переменная определена.

Область памяти , используемая программой C, включает четыре подзоны:
1. Текстовая область: где хранится код программы.
2. Область данных: где размещены глобальные переменные.
3. Область стека: где хранятся временные данные (локальные переменные)
4. Зона кучи: место, где производится динамическое выделение памяти

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

2. Авто : Память автоматически выделяется, когда функция активируется в области стека, назначенной программе, и автоматически освобождается, когда функция завершается. Локальные переменные блока (функции) и формальные аргументы являются неявными в классе auto.

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

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

Локальные переменные блока (функция) и формальные параметры являются неявными в классе auto.

Оставить комментарий

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

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