Где сохраняются константы в памяти
Константа, переменная — это базовые понятия в любом языке программирования. Дадим им определения.
Константа — это величина, которая при выполнении программы остаётся неизменной.
Переменная — это ячейка памяти для временного хранения данных. Предполагается, что в процессе выполнения программы значения переменных могут изменяться.
Описание и инициализация переменных
Прежде чем использовать в программе какую-то переменную, надо дать ей описание , то есть сказать, какое имя имеет переменная и каков её тип. Вначале указывается тип переменной, а затем её имя. Например:
int k; // это переменная целого типа int
double x; // это переменная вещественного типа удвоенной точности
Если имеется несколько переменных одного типа, то допускается их описание через запятую в одном операторе, например:
После описания переменной её можно использовать, но возникает вопрос: а какое значение имеет переменная сразу же после её описания? Ответ таков: в программе на языке C или C++ переменная после описания имеет произвольное значение , то есть ей просто выделяется свободный участок памяти и на этом всё заканчивается. В переменной хранится та последовательность двоичных цифр, которая была там до выделения памяти под эту переменную. Такой подход таит определённую опасность: можно по ошибке использовать в выражении переменную, которой не было присвоено ни какое значение:
Так как переменная x ни как не была определена, т. е. имела произвольное значение (чаще всего — это очень большое число или наоборот — очень маленькое), то и переменная y получит явно не то значение, на которое рассчитывал пользователь.
Чтобы избежать такой ошибки, Бьерн Страуструп рекомендует инициализировать переменные , то есть не просто выделять память под переменные, но и задавать им при этом необходимые значения. Например:
double a=3, b=4, c=5;
Инициализация переменных выполняется один раз на этапе компиляции, она не снижает скорость работы программы, но при этом уменьшает риск использования переменной, которая не получила ни какого значения.
Задание и использование констант
Выше было дано определение констант. Теперь рассмотрим работу с константами более подробно.
Все константы вне зависимости от типа данных можно подразделить на две категории: именованные константы и константы, которые не имеют собственного имени. Например:
25 — константа целого типа;
3.14 — вещественная константа;
‘A’ — символьная константа.
Все три приведённые здесь константы не имеют имени, они заданы своим внешним представлением и используются в программе непосредственно, например так:
int k=25; // переменная k инициализирована константой — целым числом 25.
В ряде случаев константе удобнее дать имя и использовать её далее по имени. Обычно это делается для математических или физических констант.
В языке C был единственный способ создания именованных констант — с помощью директивы препроцессора #define , например:
t = PI * 2; // здесь использована именованная константа PI, заданная выше
В языке C++ появился ещё один способ — использование константных переменных , то есть переменных, которые нельзя изменять после инициализации. Рассмотрим на том же примере:
const double PI=3.14; // здесь PI — константная переменная
В чём преимущество от использования константных переменных вместо задания констант с помощью директивы препроцессора #define ? Всё очень просто: при использовании константной переменной компилятор проверяет правильность задания константы, и если она будет задана неверно, то будет выдана ошибка именно в операторе, в котором дано определение константной переменной.
Если использована именованная константа, заданная директивой препроцессора #define , то ошибка будет показана только там, где используется константа. Например:
// в директиве препроцессора сделаем ошибку:
t = PI * 2; // в этой строке компилятор выдаст ошибку,
// хотя на самом деле ошибка допущена гораздо раньше!
Где сохраняются константы в памяти
Все компиляторы языка программирования генерируют код, который во время выполнения хранится в оперативной памяти. Размещение данных в памяти, чтобы память была зарезервирована в exe-модуле, осуществляется по формуле:
Определение Объявление = инициализация;
int i=1; // тип идентификатор=значение
Время жизни переменных – это время, в течение которого переменная хранится в определенной области памяти. Время жизни переменных полностью определяется программистом. С понятием время жизни тесно связано понятие видимости (действия) переменных, которое бывает:
- глобальное, когда в любой момент во время работы с переменной всегда ассоциирована область памяти и обратиться к ней можно из любой точки программы;
- статическое, когда во время работы с переменной ассоциирована область памяти, но обратиться к ней можно только из определенных точек программы;
- локальное, когда при каждом входе в блок операторов < >для хранения переменной выделяется область памяти, а при выходе память освобождается и переменная теряет свое значение.
Для управления статическим размещением переменных в памяти, их временем жизни и областью видимости язык программирования C++ предоставляет понятие классов памяти и ряд ключевых слов модификаторов типа:
- extern используется для определения глобальных переменных. Память для переменных extern распределяется постоянно. Такая переменная глобальна для всех функций и доступна в любой точке программы. Значение переменной всегда сохраняется.
- static используется для определения статических переменных. Статические определения используются в случае если необходимо сохранять предыдущее значение при повторном входе в блок операторов < >. Такая переменная инициализируется единственный раз, когда программа встречает ее объявление.
- auto используются для определения автоматических переменных. Переменные определенные внутри функции или блока операторов < >по умолчанию являются автоматическими. При входе в блок < >программа автоматически располагает переменную в сегменте стека. При выходе из блока память освобождается, а значения теряются.
- register используются для определения регистровых переменных. Переменные с классом памяти register, ассоциируются со скоростными регистрами памяти процессора. Но это не всегда возможно, поэтому часто компилятор преобразует такие переменные к классу auto.
Переменные extern и static явно не инициализированные программистом устанавливаются системой в нуль. Переменные auto и register не инициализируются и могут содержать «мусор».
Глобальные переменные создаются путем размещения их объявлений за пределами определений любых классов или функций. Глобальные переменные сохраняют свои значения в течение всего выполнения программы. На глобальные переменные и функции может ссылаться любая функция, которая расположена в исходном файле после их объявления или описания.
Идентификаторы, объявленные внутри блока, имеют область действия блока. Область действия блока начинается от объявления идентификатора и заканчивается завершающей правой фигурной скобкой блока, в котором идентификатор объявляется. Локальные переменные функции имеют область действия блока, как и параметры функции, которые также являются ее локальными переменными.
Если блоки вложены, и идентификатор во внешнем блоке имеет такое же имя, как идентификатор во внутреннем блоке, идентификатор внешнего блока «скрыт» до момента завершения работы внутреннего блока. Это означает, что пока выполняется внутренний блок, он «видит» значение своего собственного локального идентификатора, а не значение идентификатора с тем же именем в охватывающем блоке.
Программа демонстрирует области действия глобальных переменных, автоматических локальных переменных и статических локальных переменных.
///////////////////////////////////////////////////////////////////////////// // Прикладное программирование // Пример 13. Область действия переменных // // Кафедра Прикладной и компьютерной оптики, http://aco.ifmo.ru // Университет ИТМО ///////////////////////////////////////////////////////////////////////////// // подключение библиотеки ввода-вывода #include // подключение стандартного пространства имен для использования библиотек using namespace std; // прототипы функций void use_local(); void use_static_local(); void use_global(); ///////////////////////////////////////////////////////////////////////////// int x = 1; // глобальная переменная ///////////////////////////////////////////////////////////////////////////// void main() < int x = 5; // переменная, локальная в main cout"local x="// скобки начинает новую область действия int x = 7; // скрывает х во внешней области действия cout"local x inside < =" // конец новой области действия cout"local x after < ="<// use_local имеет локальную х use_static_local(); // use_static_local имеет статическую локальную х use_global(); // use_global использует глобальную х use_local (); // use_local повторно инициализирует свою локальную х use_static_local(); // статическая локальная х сохраняет значение use_global(); // глобальная х также сохраняет свое значение cout< ///////////////////////////////////////////////////////////////////////////// // функция реинициализирует локальную х при каждом вызове void use_local() < int x = 25; // инициализируется при каждом вызове функции cout< ///////////////////////////////////////////////////////////////////////////// // функция инициализирует статическую локальную переменную х // только при первом вызове функции; между вызовами этой функции // значение х сохраняется void use_static_local() < static int x = 50; // инициализируется при первом вызове функции cout"use_static_local: x="< ///////////////////////////////////////////////////////////////////////////// // функция модифицирует глобальную переменную х при каждом вызове void use_global() < cout"use_global: x="< /////////////////////////////////////////////////////////////////////////////
Константные переменные
Ключевое слово сonst означает что переменная инициализируется один раз после объявления и ее значение не модифицируемое:
const double pi=3.14159265358979;
Еще один вариант использования глобальных констант:
#define PI 3.14159265358979
В какой области памяти Java хранятся константы?
Область памяти пула констант времени выполнения выделяется для каждого класса или интерфейса, поэтому она вообще не привязана ни к одному экземпляру объекта. Пул констант времени выполнения является подмножеством области метода, в которой «хранятся структуры для каждого класса, такие как пул констант времени выполнения, данные полей и методов, а также код для методов и конструкторов, включая специальные методы, используемые при инициализации класса и экземпляра и интерфейсе инициализация типа «.
Максим ШубелькоУченик (123) 2 года назад
А где находится пул констант? Строкове константы (String pool) в heap, других типов тоже?
λ Искусственный Интеллект (216356) Максим Шубелько, в heap
Остальные ответы
Хранение данных в программе: литералы, константы, переменные
Всё программирование сводится к тому, чтобы манипулировать какими‐нибудь данными. Данные хранятся не просто так «в воздухе», а физически размещаются в оперативной памяти компьютера. В исходном коде данные представлены литералами, константами и переменными.
Константы и литералы
Литералы
Литерал Безымянная область памяти, которая не может изменяться. Это числа и строки, записанные в тексте программы «как есть».
Число (числовой литерал) может быть записано в десятичной, шестнадцатеричной, восьмеричной и двоичной системах счисления, используя специальные префиксы.
| Система счисления | Префикс | Пример |
|---|---|---|
| Десятеричная | Отсутствует | 234 |
| Шестнадцатеричная | &h или &H | &hEA |
| Двоичная | &b или &B | &b11101010 |
| Восьмеричная | &o или &O | &o352 |
Константы
Константа Именованная область памяти, которую нельзя изменять.
Константы объявляются в тексте программы с помощью ключевого слова Const по такой схеме:
Const ИмяКонстанты [ As ТипДанных ] = Литерал
Тип данных, который хранит константа, указывать не обязательно.
Константу необходимо объявлять вместе с инициализирующим значением, иначе компилятор сообщит об ошибке.
Примеры
' Объявляем константу количества месяцев в году Const MonthsInYear = 12 ' Объявляем константу числа пи Const Pi = 3.141592653
В данном примере MonthsInYear и Pi являются константами, а 12 и 3.141592356 — литералами.
Если попытаться присвоить константе какое‐нибудь значение, то это вызовет ошибку компиляции:
' Объявляем константу количества секунд в минуте Const SecondsInMinute = 60 ' Пробуем изменить её SecondsInMinute = 70
C:\Programming\FreeBASIC Projects>fbc HelloWorld.bas HelloWorld.bas(5) error 119: Cannot modify a constant, before '=' in 'SecondsInMinute = 70 C:\Programming\FreeBASIC Projects>_
Объявлять можно не только числовые константы, но и строковые:
Const HelloWorld = "Привет, мир!"
HelloWorld — это константа, а строка «Привет, мир!» — литерал. Обрати внимание, что кавычки не являются частью данных, а лишь ограничивают их. Как же в таком случае поместить кавычку внутрь литерала? Достаточно её удвоить:
Const QuotationLiteral = "Вот это "" кавычка внутри литерала"
Технически строковый литерал представляет собой массив символов, в конце которого компилятор добавляет символ с кодом 0, чтобы программе можно было определить конец этого массива (конец строки).
Зачем нужны константы
Константы упрощают отладку и сопровождение программ:
- исчезает необходимость помнить конкретные числа — имена запоминаются легче;
- компилятор автоматически выявляют ошибки в именах;
- упрощается внесение изменений: значение константы задано в программе всего в одном месте.
Переменные
Переменная Именованная область памяти, которую можно изменять.
Любая переменная должна быть объявлена до её использования. Переменные объявляются через операторы Dim и var .
Как допустимо называть переменные
У любой переменной должно быть имя. FreeBASIC разрешает использовать в имени переменной только английские буквы, цифры и символ подчёркивания _ , причём имя переменной не может начинаться с цифры.
Примеры допустимых имён
| Имя переменной | Пояснение |
|---|---|
| a1 | Присутствуют только английские буквы и цифра |
| _board | Присутствуют только английские буквы и подчёркивание |
| Super_Mega_Power | Присутствуют только английские буквы и подчёркивание |
| i | Присутствуют только английские буквы |
Примеры недопустимых имён
Компилятор выдаст ошибку и откажется создавать программу при виде таких имён:
| Имя переменной | Причина недопустимого имени |
|---|---|
| 1variable | Имя начинается с цифры |
| Variable& | Присутствуют недопустимые символы |
| Переменная | Присутствуют неанглийские буквы |
У всех BASIC‐подобных языков есть особенность: большие и маленькие буквы в именах переменных, операторов и функций не различаются, поэтому компилятор будет считать Variable и vAriaBLE одним и тем же именем.
Объявление переменных через оператор Dim
Переменные через оператор Dim объявляются по следующей схеме:
Dim ИмяПеременной As ТипДанных [ = Выражение]
Выражением может быть любой литерал, константа, результат выполнения функции или другая переменная. Единственное здесь условие: типы данных переменной и выражения должны совпадать.
' Объявляем целочисленную переменную Dim x As Integer ' Также переменные можно объявлять сразу же вместе с начальным значением Dim y As Integer = 35
В одной строке можно объявлять несколько переменных через запятую. В таком случае спецификатор типа следует указывать вначале:
Dim As Integer x, y
Если для переменной не указывать инициализирующее значение, то FreeBASIC инициализирует её значением по умолчанию. Чисел и указатели инициализируются нулём, булёвые величины — False , строки — строкой нулевой длины.
Объявление переменных через оператор var
Через оператор var переменные объявляют без указания типа данных, но сразу же с инициализирующим значением. Тип переменной автоматически определится из инициализирующего выражения.
var ИмяПеременной = Выражение
Это удобно и немного сокращает код:
' Объявим переменную, в которой будет храниться длина var length = 5
Через оператор var можно объявить несколько переменных сразу через запятую:
' Объявим несколько переменных в одной строке var UserId = 251994, Rational = 2.54
Переменная UserId будет типа Integer , переменная Rational будет типа Double .
Указатели
Данные хранятся в памяти компьютера. Память можно представить как последовательный набор пронумерованных коробок начиная от нуля, и размером в 1 байт. Обращаться к данным в этих коробках можно по их номеру, то есть адресу.
Указатель Область памяти, которая хранит в себе «номер коробки» (адрес) где находятся данные.
Обычная переменная позволяет обращаться к данным по имени, указатель — по адресу.
Объявление указателей
Указатель, как и любая переменная, должен быть объявлен. Указатели объявляют почти также, как и обычные переменные, но с добавлением ключевых слов Ptr или Pointer . Указатели можно объявлять через оператор Dim или var по таким схемам:
' Первый вариант Dim ИмяУказателя As ТипДанных Ptr [ = Адрес] ' Второй вариант, менее распространён Dim ИмяУказателя As ТипДанных Pointer [ = Адрес]
Указатель хранит в себе номер коробки, где лежат данные определённого типа. Какого именно типа — определяется при объявлении указателя:
' Объявим указатель на целочисленные данные Dim pInt As Integer Ptr ' Объявим указатель на байт Dim pByte As Byte Ptr ' Можно объявлять указатель, который будет указывать на другой адрес, где хранятся данные Dim pIntInt As Integer Ptr Ptr
Тип указателя должен соответствовать типу переменной, на которую он указывает. При присваивании указателю адреса не на тот тип данных, фрибейсик при компиляции выдаст предупреждение.
Получение адреса переменной
Каждая переменная в памяти имеет свой адрес — номер первой коробки, где она расположена, а также своё значение. Как же получить адрес данных, которые хранятся в переменной?
Для этого существует оператор @ ( VarPtr )— он возвращает адрес объекта.
' Объявим целую переменную и запишем туда данные Dim Days As Integer = 15 ' Объявим указатель и получим адрес переменной Dim pDays As Integer Ptr = @Days ' Распечатаем адрес Print "pDays = "; pDays
Результат работы программы:
C:\Programming\FreeBASIC Projects>Pointers.exe pDays = 1375744 C:\Programming\FreeBASIC Projects>_
Как видно, данные в переменной Days находятся по адресу 1375744. У тебя этот адрес наверняка будет другим, потому что программы могут загружаться в оперативную память по разным адресам.
Следует отметить, что операцию взятия адреса @ неприменима к литералам и константам, потому что у них нет адреса.
Получение данных по адресу
Для того, чтобы извлечь данные, на которые ссылается указатель, существует оператор * — он возвращает ссылку на значение, хранящееся по адресу. Такая операция называется «разыменование указателя».
Не следует путать операцию разыменования и умножение, которое тоже обозначается звёздочкой. Разыменование указателя — это унарная операция, то есть в ней участвует один операнд; умножение — бинарная операция, в ней участвуют два операнда.
' Объявим целую переменную и запишем туда данные Dim Days As Integer = 15 ' Объявим указатель и получим адрес переменной Dim pDays As Integer Ptr = @Days ' Получим данные, которые хранятся по адресу указателя Dim OriginalDays As Integer = *pDays Print "OriginalDays = "; OriginalDays ' Распечатаем данные, на которые ссылается указатель Print "*pDays = "; *pDays ' Перезапишем данные по указателю *pDays = 20 ' Посмотрим на оригинальную переменную, её значение будет изменено Print "Days = "; Days
Результат работы программы:
C:\Programming\FreeBASIC Projects>Pointers.exe OriginalDays = 15 *pDays = 15 Days = 20 C:\Programming\FreeBASIC Projects>_
Перед разыменованием, необходимо убедиться, что значение указателя содержит действительный адрес памяти.
Действительные и недействительные адреса
Действительный адрес Такой адрес, который указывает на настоящие данные, переменную или функцию. Недействительный адрес Адрес, указывающий не на настоящие данные, переменную или функцию.
При объявлении численной переменной без инициализации компилятор автоматически инициализирует её и записывает в неё 0. Указатель также является целочисленной беззнаковой переменной, поэтому он тоже будет инициализирован нулём.
' Объявим указатель без инициализации Dim pDays As Integer Ptr ' В нём находится ноль Print "pDays = "; pDays
C:\Programming\FreeBASIC Projects>Pointers.exe pDays = 0 C:\Programming\FreeBASIC Projects>_
Ящик с номером ноль — это специальное зарезервированное значение адреса, что указатель содержит недействительный адрес. При любой операции к такой памяти процессор генерирует специальное прерывание, операционная система перехватывает это прерывание и завершает вызвавший его процесс с ошибкой времени выполнения: «Программа выполнила недопустимую операцию и будет закрыта».
Разыменование указателя с недействительным адресом является операцией с неопределённым поведением. Это значит, что может произойти всё, что угодно: обращение к непредназначенной для использования данной программой памяти, запись в непринадлежащие программе данные, завершение процесса, зависание всей системы или что угодно другое:
Dim p As Integer Ptr ' Указателю не присвоен действительный адрес, разыменовывать его нельзя ' Следующая строка приведёт к неопределённому поведению Print *p
Упражнения
- Какой тип данных будет лучшим для хранения числа 196?
- Какой тип данных будет лучшим для хранения числа 2.134?
- Какой тип данных является наилучшим для общего использования в 32‐битных системах? А в 64‐битных системах?
- В чём разница между знаковыми и беззнаковыми типами данных?
- Какой префикс ты будешь использовать для обозначения двоичного числа?
- Какой префикс ты будешь использовать для обозначения шестнадцатеричного числа?
- Какие буквы допускаются в шестнадцатеричном числе?
- Дано шестнадцатеричное число: 1AF. Переведи в десятичное число.
Поблагодарить

«Пакетные файлы» создали этот сайт 11 марта 2016 года