При изучении большинства языков программирования мы часто встречаемся с таким понятием, как переменная. Однако на начальных этапах не всегда может быть ясно, о чем же идет речь. В этой статье мы объясним простыми словами, что такое переменные в программировании и для чего они нужны.
Формальное определение переменной звучит так: «поименованная либо адресуемая иным способом область памяти, адрес которой можно использовать для осуществления доступа к данным».
Такое объяснение может показаться достаточно сложным. Но попробуем разобраться на примере и увидим, что на самом деле переменная — это просто!
Представим себе задачу: нам нужно написать программу, которая будет посылать по электронной почте друзьям и родственникам письмо с приглашением в гости. Хорошо, если это письмо будет начинаться с приветствия. Например: «Привет, Саша!» или «Привет, мама!».
Но ведь в таком случае мы не сможем использовать один и тот же шаблон для всех адресатов? Как вы уже могли догадаться — сможем, и здесь нам на помощь как раз придут переменные. Нам нужно всего лишь завести для имени адреса переменную (назовем ее name ) и задавать ей нужное значение перед отправкой письма (подробнее об объявлении переменных мы поговорим ниже):
Что такое переменная в программировании.
String name = «Иван»
И теперь шаблон приветствия нашего письма будет выглядеть так:
Представим, что переменная — это коробочка, в которую мы можем что-то положить. То, что лежит в коробочке, будет называться значением переменной .
Переменная и ее значение
Также в ходе выполнения программы мы можем, например, это значение достать и положить другое. Это будет значить, что переменная изменилась.
Такое объяснение достаточно близко к тому, как на самом деле устроено хранение в памяти компьютера: переменная — это выделенная область памяти, в которой хранятся наши данные.
Давайте рассмотрим еще один пример использования переменных.
Как объявляются переменные в программах
Этот раздел является переводом туториала C++ Language
Полезность программы «Hello, world», рассмотренной в предыдущем разделе, весьма сомнительна. Нам пришлось написать несколько строк кода, скомпилировать их, а затем выполнить полученную программу для того, чтобы в результате получить простое предложение, написанное на экране. Намного быстрее ввести это предложение вручную.
Тем не менее программирование не ограничивается печатью простых текстов на экране. Для того чтобы пойти немного дальше и получить возможность писать программы, которые выполняют полезные задачи, реально помогающие в работе, нам нужно ввести понятие переменных.
Давайте представим, что я попрошу Вас запомнить число 5, а затем я попрошу запомнить также число 2 в то же самое время. Вы только что сохранили два различных значения в памяти (5 и 2). Сейчас, если я попрошу Вас прибавить 1 к первому числу, которое я назвал, Вы должны сохранить число 6 (т.е. 5+1) и 2 в своей памяти. Теперь мы можем, например, вычесть эти значения и получить 4 в качестве результата.
Python для начинающих. Как работают переменные в Python. #2
Весь процесс, описанный выше, это подобие того, что компьютер может делать с двумя переменными. Такой же процесс может быть выражен в C++ следующим набором операторов:
a = 5; b = 2; a = a + 1; result = a — b;
Очевидно, что это очень простой пример, так как мы использовали только два небольших целочисленных значения, но компьютер может хранить миллионы чисел в одно и то же время и производить сложные математические операции с ними.
Таким образом, мы можем определить переменную, как область памяти для хранения значения.
Каждой переменной нужно имя, которое идентифицирует его и отличает от других. Например, в предыдущем коде именами переменных были a, b и result, но мы можем называть переменные любыми именами, если они являются допустимыми идентификаторами в C++.
Идентификаторы
Допустимый идентификатор — это последовательность одной или нескольких букв, цифр или символов подчеркивания (_). Пробелы, знаки пунктуации и другие символы не могут быть частью идентификатора. Кроме того, идентификаторы должны всегда начинаться с буквы. Они также могут начинаться с символа подчеркивания (_), но такие идентификаторы в большинстве случаев считаются зарезервированными для специфичных для компилятора ключевых слов или внешних идентификаторов, так же как и идентификаторы, содержащие два последовательных символа подчеркивания в любом месте. Идентификаторы не могут начинаться с цифры.
C++ использует набор ключевых слов для определения операций и описания данных; таким образом, идентификаторы, созданные программистом, не могут совпадать с этими ключевыми словами:
alignas, alignof, and, and_eq, asm, auto, bitand, bitor, bool, break, case, catch, char, char16_t, char32_t, class, compl, const, constexpr, const_cast, continue, decltype, default, delete, do, double, dynamic_cast, else, enum, explicit, export, extern, false, float, for, friend, goto, if, inline, int, long, mutable, namespace, new, noexcept, not, not_eq, nullptr, operator, or, or_eq, private, protected, public, register, reinterpret_cast, return, short, signed, sizeof, static, static_assert, static_cast, struct, switch, template, this, thread_local, throw, true, try, typedef, typeid, typename, union, unsigned, using, virtual, void, volatile, wchar_t, while, xor, xor_eq
Очень важно: язык C++ является языком, чувствительным к регистру. Это означает, что идентификатор, написанный заглавными буквами, не является эквивалентом другому идентификатору с тем же именем, записанным маленькими буквами. Так, например, переменная RESULT это не то же самое, что переменная result или Result. Это три разных идентификатора, обозначающих три различные переменные.
Основные типы данных
Значения переменных хранятся где-то в неопределенном месте памяти компьютера в виде нулей и единиц. Нашей программе нет необходимости знать точное место хранения переменной; она может просто ссылаться на него по имени переменной. Что нужно программе, чтобы понять, какой тип данных хранится в переменной? Хранение целого числа, буквы или большого числа с плавающей точкой неодинаково; даже несмотря на то что они представлены в виде нулей и единиц, интерпретируются они по-разному, и во многих случаях занимают различное количество памяти.
Основные типы данных — это типы, реализованные непосредственно в языке, и представляют собой основные единицы хранения данных, изначально поддерживаемые большинством систем. Главным образом, они могут быть разделены на:
- Символьные типы: Они могут представлять единичный символ, такой как ‘A’ или ‘$’. Самым простым типом является тип char, представляющий собой однобайтовый символ. Также предоставляются другие типы для более «широких» символов. Про широкобайтовую кодировку довольно неплохо написано в начале книги «Windows via C/C++» авторов К.Назара, Дж.Рихтера. И, хотя книга посвящена программированию под Windows, суть вопроса излагается довольно внятно (прим. переводчика).
- Целочисленные типы: Они могут хранить значение целого числа, например 7 или 1024. Существуют эти типы различных размеров и могут быть как знаковыми, так и беззнаковыми, в зависимости от того, поддерживают они отрицательные значения или нет.
- Типы с плавающей точкой: Они могут представлять вещественные величины, такие как 3.14 или 0.01, с различной степенью точности, зависящий от того, какой тип с плавающей точкой из трех возможных используется.
- Логический тип: Логический тип данных, известный в C++ как bool, может находиться только в одном из двух состояний: true или false.
Вот полный список основных типов в C++:
| Символьные типы | char | Размер ровно один байт. Как минимум 8 бит. |
| char16_t | Не меньше, чем char. Как минимум 16 бит. | |
| char32_t | Не меньше, чем char16_t. Как минимум 32 бита. | |
| wchar_t | Представляет наибольший набор поддерживаемых символов. | |
| Целочисленные типы (знаковые) | signed char | Такого же размера, как char. Как минимум 8 бит. |
| signed short int | Не меньше, чем char. Как минимум 16 бит. | |
| signed int | Не меньше, чем short Как минимум 16 бит. | |
| signed long int | Не меньше, чем int. Как минимум 32 бита. | |
| signed long long int | Не меньше, чем long. Как минимум 64 бита. | |
| Целочисленные типы (беззнаковые) | unsigned char | (такой же размер, как у соответствующих знаковых типов) |
| unsigned short int | ||
| unsigned int | ||
| unsigned long int | ||
| unsigned long long int | ||
| Типы с плавающей точкой | float | |
| double | Точность не меньше, чем у float | |
| long double | Точность не меньше, чем у double | |
| Логический тип | bool | |
| Тип void | void | не хранится |
| Пустой указатель (null pointer) | decltype(nullptr) |
* Имена некоторых целочисленных типов могут быть кратко записаны без компонентов signed или int — для идентификации типа требуется только часть имени, записанная не курсивом; часть, записанная курсивом, является необязательной. То есть signed short int может быть сокращено до signed short, short int или просто short; все это идентифицирует один и тот же основной тип.
Внутри каждой группы выше различия между типами заключается только в их размере (то есть, сколько места они занимают в памяти): первый тип в каждой группе является наименьшим, а последний наибольшим, каждый тип как минимум не меньше, чем предыдущий в той же группе. Кроме того, типы в группе имеют одни и те же свойства.
Обратите внимание, что в таблице за исключением типа char (который имеет размер ровно один байт), ни один из основных типов не имеет определенного стандартного размера (кроме минимального размера, в большинстве случаев). Таким образом, типы не требуют (и во многих случаях не соответствуют) именно этого минимального размера. Это не означает, что размер этих типов не определен, но не существует стандартного размера для всех компиляторов и машин; каждая реализация компилятора может определять размеры для этих типов, которые наилучшим образом соответствуют архитектуре, на которой будет работать программа. Эта довольно общая спецификация для типов предоставляет языку C++ много гибкости, чтобы быть адаптированным для оптимальной работы на всех типах платформ настоящего и будущего.
Размеры типов выражены в битах; чем больше битов имеет тип, тем больше он может принимать уникальных значений, но в то же время, требует больше пространства в памяти:
| 8 бит | 256 | =2 8 |
| 16 бит | 65 536 | =2 16 |
| 32 бита | 4 294 967 296 | =2 32 |
| 64 бита | 18 446 744 073 709 551 616 | =2 64 |
Если целочисленный тип имеет разные представления (как знаковый, так и беззнаковый), то это означает, что диапазон значений, который он может принимать, шире; например, 16-битное беззнаковое целое может принимать 65536 различных значений в диапазоне от 0 до 65535, в то время как соответствующее ему знаковое представление может принимать, в большинстве случаев, значения от -32768 до 32767. Обратите внимание, что диапазон положительных значений примерно вдвое меньше в знаковых типах по сравнению с беззнаковыми, так как один из 16 бит используется для знака; это относительно небольшое различие в диапазонах и редко оправдывает использование беззнаковых типов, основанное исключительно на диапазоне положительных значений, который они могут принимать.
Для типов с плавающей точкой, размер влияет на их точность использованием большего или меньшего числа бит для мантиссы и экспоненты.
Если размер или точность типа не является проблемой, тогда обычно используются типы char, int и double для представления символов, целых чисел и значений с плавающей точкой соответственно. Другие типы в соответствующих группах используются только в весьма специфических случаях.
Свойства основных типов в конкретной реализации системы и компилятора можно получить с помощью классов numeric_limits (см. стандартный заголовочный файл ). Если по некоторым причинам требуются типы определенных размеров, библиотека определяет конкретные псевдонимы типа фиксированного размера в заголовке .
Типы, описанные выше (символы, целые числа, числа с плавающей точкой и логический тип), известны как арифметические типы. Но существуют два дополнительных основных типа: void, обозначающий отсутствие типа, и тип nullptr, который представляет собой особый тип указателя. Оба типа будут обсуждаться подробнее в главе об указателях.
C++ поддерживает разнообразные типы, базирующиеся на основных типах, рассмотренных выше; эти другие типы известны как составные типы данных и являются одни из основных преимуществ языка C++. Мы также рассмотрим их более подробно в будущих главах.
Объявление переменных
C++ является языком со строгой типизацией и требует объявления типа каждой переменной перед ее использованием. Это сообщает компилятору размер памяти, резервируемый для переменной, и интерпретацию ее значения. Синтаксис для объявления новой переменной в C++ прост: мы просто пишем тип переменной перед ее именем (т.е. идентификатором). Например:
int a; float mynumber;
Это два допустимых объявления переменных. В первом объявляется переменная типа int с идентификатором a. Во втором объявляется переменная типа float с идентификатором mynumber. Определенные однажды, эти переменные могут быть использованы во всей своей области видимости.
Если объявляется более одной переменной одного и того же типа, то их можно объявить в одном выражении, разделяя запятыми. Например:
int a, b, c;
Здесь определяются три переменных (a, b и c), все они типа int. Это выражение имеет точно такой же смысл, что и:
int a; int b; int c;
Чтобы увидеть, что из себя представляют объявления переменных в программе, давайте посмотрим на весь C++ код примера о Вашей умственной памяти, предложенный в начале этой главы:
// работа с переменными #include using namespace std; int main () < // объявление переменных: int a, b; int result; // работа: a = 5; b = 2; a = a + 1; result = a — b; // печать результата: cout
Не беспокойтесь, если что-либо, кроме самих объявлений переменных, выглядит для Вас странно. Большая часть будет объяснена более детально в следующих главах.
Инициализация переменных
Когда переменные в приведенном выше примере объявляются, они имеют неопределенное значение до тех пор, пока им не присваивается значение в первый раз. Но переменная может иметь определенное значение с момента объявления. Это называется инициализацией переменной.
В C++ есть три способа инициализировать переменные. Они эквивалентны и напоминают эволюцию языка с годами:
Первый, известный как c-like initialization (потому что он унаследован от языка Си), состоит в добавлении знака равенства, за которым следует значение, присваиваемое инициализируемой переменной:
type identifier = initial_value;
Например, чтобы объявить переменную типа int с именем x и инициализировать ее нулем с момента объявления, мы можем написать:
int x = 0;
Второй метод, известный как инициализация в конструкторе (введен в язык C++), заключает начальное значение в круглые скобки (()):
type identifier (initial_value);
int x (0);
Наконец, третий метод, известный как универсальная инициализация, похож на предыдущий, но использует фигурные скобки (<>) вместо круглых (введен после пересмотра стандарта C++, в 2011 году):
int x ;
Все три способа инициализации переменных являются корректными и эквивалентными в C++.
// инициализация переменных #include using namespace std; int main () < int a=5; // начальное значение: 5 int b(3); // начальное значение: 3 int c; // начальное значение: 2 int result; // начальное значение не определено a = a + b; result = a — c; cout
Определение типа: auto и decltype
При инициализации новой переменной компилятор может определить тип переменной автоматически через инициализатор. Для этого достаточно использовать auto как описатель типа для переменной:
int foo = 0; auto bar = foo; // то же самое, что: int bar = foo;
Здесь bar объявляется типом auto; таким образом, тип bar — это тип значения, используемого для его инициализации: в данном случае используется тип переменной foo, т.е. тип int.
Переменные, которые не инициализируются, также могут использовать определение типа со спецификатором decltype:
int foo = 0; decltype(foo) bar; // то же, что: int bar;
auto и decltype — это мощные средства, недавно добавленные в язык. Но определение типа этими средствами предназначено для использования либо когда тип не может быть получен другими средствами, либо когда их использование улучшает читаемость кода. Два примера выше, вероятно, не являются такими случаями. На самом деле, они, вероятно, ухудшили читаемость, поскольку во время чтения кода необходимо найти тип foo, чтобы узнать тип bar.
Введение в строки
Основные типы представляют наиболее простые типы, обрабатываемые на машинах, на которых может выполняться код. Но одна из основных сильных сторон языка C++ — это его богатый набор составных типов, строительными блоками для которых являются основные типы.
Пример составного типа это класс строки. Переменные этого типа способны хранить последовательности символов, такие как слова или предложения. Очень полезная функция!
Первым отличием от основных типов данных является то, что для объявления и использования объектов (переменных) этого типа, программа должна включать заголовок стандартной библиотеки, в котором определен тип (заголовок <string>):
// моя первая строка #include #include using namespace std; int main ()
This is a string
Как Вы можете видеть в предыдущем примере, строки могут быть инициализированы любым корректным строковым литералом, так же как переменные арифметических типов могут быть инициализированы любым корректным числовым литералом. Как и в случае с основными типами, для строк являются допустимыми все формы инициализации:
string mystring = «This is a string»; string mystring («This is a string»); string mystring ;
Строки могут также производить все другие основные операции, которые доступны для основных типов, как то объявление без инициализации и изменение его значения во время выполнения:
// моя первая строка #include #include using namespace std; int main ()
This is the initial string content This is a different string content
Примечание: вставка манипулятора endl завершает строку (печатает символ новой строки).
Класс string это составной тип. Как вы можете видеть в приведенном выше примере, составные типы используются так же, как базовые типы: тот же синтаксис используется для объявления переменных и для их инициализации.
Для более подробной информации о стандартных строках C++ смотрите справку по классу string.
Источник: pvoid.pro