Лекции / ИСПОЛЬЗОВАНИЕ ПЕРЕМЕННЫХ И ТИПИЗАЦИЯ ДАННЫХ
.pdfГЛАВА 3. ИСПОЛЬЗОВАНИЕ ПЕРЕМЕННЫХ И ТИПИЗАЦИЯ |
|
ДАННЫХ |
|
Оглавление |
|
§3.1 Определение переменной и константы......................................................... |
2 |
§3.2 Объявление переменных для получения доступа и использования памяти |
|
................................................................................................................................... |
3 |
§3.3 Область видимости переменной.................................................................... |
6 |
§3.3.1 Глобальные переменные ............................................................................. |
8 |
§3.3.2 Локальные переменные ............................................................................... |
9 |
§3.4 l-values и r-values ........................................................................................... |
10 |
§3.5 Типы данных.................................................................................................. |
11 |
§3.5.1 Тип данных bool ......................................................................................... |
12 |
§3.5.2 Тип данных char ......................................................................................... |
13 |
§3.5.3 Тип данных int ............................................................................................ |
14 |
§3.5.4 Тип данных с плавающей точкой ............................................................. |
15 |
§3.5.5 Дополнительные типы данных ................................................................. |
16 |
§3.6 Определение размера переменной .............................................................. |
16 |
§3.7 Неявное определение типов ......................................................................... |
17 |
§3.8 Константа ....................................................................................................... |
18 |
§3.9 Арифметические операторы ........................................................................ |
19 |
§3.10 Операторы сравнения и присваивания ..................................................... |
22 |
§3.11 Логические операторы................................................................................ |
25 |
§3.12 Приоритет операций ................................................................................... |
28 |
§3.13 Определение типа переменной .................................................................. |
33 |
§3.14 Неявное преобразование типов ................................................................. |
34 |
§3.15 Явное преобразование типов ..................................................................... |
35 |
§3.16 Математические функции .......................................................................... |
38 |
§3.1 Определение переменной и константы
Переменная (variable) – это средство, позволяющее программисту временно сохранить данные. Переменная представляет именованную область памяти, в которой хранится значение определенного типа. Переменная имеет тип, имя и значение. Тип определяет, какого рода информацию может хранить переменная.
Константа – это средство, позволяющее программисту определить элемент, которому не позволено изменяться.
Все компьютеры, смартфоны и другие программируемые устройства имеют микропроцессор и определенный объем памяти для временного хранения данных, называемый оперативной памятью (Random Access Memory
– RAD). Кроме того, многие устройства позволяют сохранять данные на долгосрочном запоминающем устройстве, таком как жесткий диск.
Микропроцессор выполняет ваше приложение и использует при этом оперативную память для его загрузки, а также для связанных с ним данных,
включая те, которые отображаются на экране и вводятся пользователем.
Саму оперативную память, являющуюся областью хранения, можно сравнить с рядом шкафчиков в общежитии, каждый из которых имеет свой номер, т.е. адрес. Чтобы получить доступ к области в памяти, скажем 876-й,
процессору нужно с помощи специальных инструкций попросить выбрать оттуда значение или записать значение в нее.
Литеральные константы (или просто «литералы») — это значения,
которые вставляются непосредственно в код. Поскольку они являются константами, то их значения изменить нельзя. Литералы бывают логическими,
целочисленными, вещественными, символьными и строчными. И отдельный литерал представляет ключевое слово null. Например:
bool myNameIsAlex = true; // true – это логический литерал int x = 5; // 5 – это целочисленный литерал
int y = 2 * 3; // 2 и 3 – это целочисленные литералы
2
cout << ‘a’; // a – символьный литерал
Console.WriteLine("hello"); // hello – это строковый литерал
Строковые литералы заключаются в двойные кавычки, а символьные
литералы – в одинарные кавычки.
§3.2 Объявление переменных для получения доступа и использования
памяти
Предположим, что надо написать программу умножения для двух чисел,
предоставляемых пользователем. Пользователя просят ввести множитель и множимое, один за другим, и каждое из этих значений необходимо хранить до момента умножения. В зависимости от того, что вы хотите делать с результатом умножения, их может понадобится хранить и для более позднего использования в программе.
При программировании на таких языках, как С++ и С#, для хранения значений определяют переменные. Определение переменной очень просто и осуществляется по следующему шаблону:
ТИП_ПЕРЕМЕННОЙ ИМЯ_ПЕРЕМЕННОЙ;
или
ТИП_ПЕРЕМЕННОЙ ИМЯ_ПЕРЕМЕННОЙ = ИСХОДНОЕ_ЗНАЧЕНИЕ;
ТИП_ПЕРЕМЕННОЙ ИМЯ_ПЕРЕМЕННОЙ(ИСХОДНОЕ_ЗНАЧЕНИЕ);
Атрибут «ТИП_ПЕРЕМЕННОЙ» указывает компилятору характер данных, который может хранить переменная, и компилятор резервирует для этого необходимое пространство.
Атрибут «ИМЯ_ПЕРЕМЕННОЙ» является более осмысленной заменой для адреса области в памяти, где хранится значение переменной.
Если исходное значение не применяется, вы не можете быть уверены в содержимом этой области памяти, что может быть плохо для программы.
Поэтому, будучи необязательной, инициализация зачастую является хорошей практикой программирования. Для инициализации переменной исходным значением применяется копирующая инициализация, выполняемая с
3
помощью знака равенства =, или прямая инициализация с помощью круглых скобок ().
Листинг 3.1 демонстрирует объявление переменных, их инициализацию и использование в программе, которая умножает два числа, предоставленных
пользователем.
|
|
|
Листинг 3.1. |
|
|
|
|
|
|
1 |
#include <iostream> |
|
|
|
|
|
|
|
|
2 |
using namespace std; |
|
|
|
|
|
|
|
|
3 |
int main () |
|
|
|
|
|
|
|
|
4 |
{ |
|
|
|
|
|
|
|
|
5 |
cout << "This |
program will help you |
multiply two |
|
numbers" << endl; |
|
|
||
|
|
|
||
|
|
|
|
|
6 |
cout << "Enter the first number: "; |
|
|
|
|
|
|
|
|
7 |
int FirstNumber = 0; |
|
|
|
|
|
|
|
|
8 |
cin >> FirstNumber; |
|
|
|
|
|
|
|
|
9 |
cout << "Enter the second number: "; |
|
|
|
|
|
|
|
|
10 |
int SecondNumber = 0; |
|
|
|
|
|
|
|
|
11 |
cin >> SecondNumber; |
|
|
|
|
|
|
|
|
12 |
// Умножение |
двух чисел, сохранение |
результата в |
|
переменной |
|
|
|
|
|
|
|
|
|
|
|
|
||
13 |
int MultiplicationResult = FirstNumber * SecondNumber; |
|
||
|
|
|
|
|
14 |
// Отображение результата |
|
|
|
|
|
|
||
15 |
cout << FirstNumber << " x " << SecondNumber; |
|
||
|
|
|
||
16 |
cout << " = " << MultiplicationResult << endl; |
|
||
|
|
|
|
|
17 |
return 0; |
|
|
|
|
|
|
|
|
18 |
} |
|
|
|
|
|
|
|
|
|
Результат выполнения программы: |
|
|
This program will help you multiply two numbers
Enter the first number: 5
4
Enter the second number: 2
5 x 2 = 10
Это приложение просит пользователя ввести два числа, результат умножения которых и отображается. Чтобы приложение могло использовать введенные пользователем числа, оно должно хранить их в памяти.
Переменные FirstNumber и SecondNumber, объявленные в строках 7 и 10,
решают задачу временного хранения введенных пользователем целочисленных значений. Операторы cin в строках 8 и 11 используются для получения введенных пользователем значений и сохранения их в двух целочисленных переменных. Оператор cout в строке 21 используется для отображения результата на консоли.
Давайте проанализируем объявление переменной подробнее:
7 int FirstNumber = 0;
Эта строка объявляет переменную типа int, который означает целое число, по имени FirstNumber. В качестве исходного значения переменной присваивается нулевой значение.
Таким образом, по сравнению с программированием на ассемблере, где необходимо явно просить процессор сохранить множитель в области памяти,
скажем 876, высокоуровневые языки программирования, такие как C++ и С#,
позволяют обратиться к области памяти для сохранения и получения данных,
используя боле дружественные концепции, такие как переменная по имени
FirstNumber. Компилятор сам выполнит задачу по сопоставлению имени этой переменной с адресом области памяти и позаботится о соответствующих действиях за вас.
Имена переменных важны для написания хорошего, понятного и удобного в сопровождении кода.
Имена же переменных задаются согласно следующим правилам:
1.Имя переменной не может начинаться с цифры.
5
2.В имени переменной не может быть пробелов, а также специальных символов (вроде ; № # % или /).
3.Имя переменной не может совпадать с другими, ранее объявленными именами (функций, переменных, стандартных операторов и т. п.).
Именами переменных не могут быть также зарезервированные ключевые слова. Например, переменная по имени return приведет к ошибке при компиляции.
Переменные в листинге 3.1 имеют одинаковый тип (целочисленный тип), но объявляются в трех отдельных строках. Запись определения этих трех переменных можно уплотнить до одной строки:
int FirstNumber = 0, SecondNumber = 0, MultiplicationResult
= 0;
§3.3 Область видимости переменной
У обычных переменных есть четко определенная область видимости
(scope), в пределах которой они допустимы и применимы. При использовании вне своих областей видимости имена переменных не будут распознаны компилятором, и ваша программа не будет откомпилирована. Вне своей области видимости переменная – неопознанная сущность, о которой компилятор ничего не знает.
В C++ существуют отдельные блоки, которые начинаются с открывающей скобки ({) и заканчиваются соответственно закрывающей скобкой (}). Такими блоками являются циклы (for, while, do while) и функции.
Листинг 3.2.
1int func () {
2// блок (функция - func)
3}
4int main() {
5// блок (функция - main)
6
6 |
for (int i = 0; i < 10; i++) { |
|
|
|
|
7 |
// блок (цикл - for), также является дочерним блоком |
|
функции main |
||
|
||
|
|
|
8 |
for (int j = 0; j < 5; j++) { |
|
|
|
|
9 |
// блок (цикл - for), но он еще является и дочерним |
|
блоком для первого цикла |
||
|
||
|
|
|
10 |
} |
|
|
|
|
11 |
} |
|
|
|
|
12 |
return 0; |
|
|
|
|
13 |
} |
|
|
|
Если переменная была создана в таком блоке, то ее областью видимости будет являться этот блок от его начала (от открывающей скобки — {) и до его конца (до закрывающей скобки — }) включая все дочерние блоки созданные в этом блоке.
Впримере ниже, программист ошибся с областью видимости:
1.Он создал переменную j во втором цикле;
2.Использовав ее в первом цикле for (строка 7) он вынудил компилятор сообщить об ошибке (переменной j больше нет, поскольку второй цикл закончил свою работу).
Листинг 3.3.
1 |
int main() { |
|
|
|
|
2 |
for (int i = 0; i < 10; i++) { |
|
|
|
|
3 |
int b = i; |
|
|
|
|
4 |
for (int j = 0; j < 5; j++) { |
|
|
|
|
5 |
cout << b + j; |
|
|
|
|
6 |
} |
|
|
|
|
7 |
cout << j; // ошибка: так как переменная j была создана |
|
в другом блоке |
||
|
||
|
|
|
|
7 |
8}
9return 0;
10}
Авот ошибки в строке 5 нет, поскольку второй цикл находится в первом цикле (является дочерним блоком первого цикла) и поэтому переменная b
может спокойно там использоваться.
§3.3.1 Глобальные переменные
Глобальными переменными называются те переменные, которые были созданы вне тела какого-то блока. Они имеют самую широкую область видимости, так как их можно всегда использовать во всей вашей программе,
вплоть до ее окончания работы.
В примере ниже мы создали две глобальные переменные global и global_too и использовали их в функции summa:
|
|
Листинг 3.4. |
|
|
|
1 |
int global = 5; |
// глобальные |
|
|
|
2 |
int global_too = 10; |
// переменные |
|
|
|
3 |
int summa() { |
|
|
|
|
4 |
cout << global + global_too; // суммируем числа = 15 |
|
|
|
|
5 |
} |
|
|
|
|
6 |
int main() { |
|
|
|
|
7 |
summa(); // вызываем функцию summa |
|
|
|
|
8 |
return 0; |
|
|
|
|
9 |
} |
|
|
|
|
Как видите глобальные переменные видны везде. В нашем примере внутри функции summa мы не создавали никакие переменные, мы лишь использовали две глобальные переменные, которые были созданы раньше.
Безосновательное использование глобальных переменных обычно считается плохой практикой программирования.
8
Значение глобальной переменной может быть присвоено в любой функции, и это значение может оказаться непредсказуемо, особенно если разные функциональные модули разрабатываются разными программистами.
§3.3.2 Локальные переменные
Локальные переменные — это переменные, которые применимы в функции от места ее объявления до конца функции. Областью видимости таких переменных является блоки (и все их дочерние), а также их область видимости не распространяется на другие блоки. Фигурная скобка (}),
означающая конец функции, означает также конец области видимости объявленных в ней переменных. Когда функция заканчивается, все ее локальные переменные ликвидируются, а занимаемая ей память освобождается.
Из этого можно сделать вывод: у нас есть возможность создавать переменные с одинаковыми именами, но в разных блоках (или другими словами, чтобы их область видимости не совпадала друг с другом).
Листинг 3.5.
1 |
int main() { |
|
|
|
|
2 |
for (int i = 0; i < 2; i++) { |
|
|
|
|
3 |
int b = i; // локальная переменная (она находится в |
|
блоке for) |
||
|
||
|
|
|
4 |
cout << b; |
|
|
|
|
5 |
} |
|
|
|
|
6 |
return 0; |
|
|
|
|
7 |
} |
|
|
|
В примере выше блоком, где была создана локальная переменная b
является цикл for (2 — 5). А вот если бы мы захотели вывести переменную b
вне блока for, компилятор сообщил бы нам об ошибке.
9
§3.4 l-values и r-values
Все переменные являются l-values. l-value (в переводе «л-значение»,
произносится как «ел-валью») — это значение, которое имеет свой собственный адрес в памяти. Поскольку все переменные имеют адреса, то они все являются l-values (например, переменные a, b, c — все они являются l- values). l от слова «left», так как только значения l-values могут находиться в левой стороне в операциях присваивания (в противном случае, мы получим ошибку). Например, стэйтмент 9 = 10; вызовет ошибку компилятора, так как 9
не является l-value. Число 9 не имеет своего адреса в памяти и, таким образом,
мы ничего не можем ему присвоить (9 = 9 и ничего здесь не изменить).
Противоположностью l-value является r-value (в переводе «р-значение»,
произносится как «ер-валью»). r-value — это значение, которое не имеет постоянного адреса в памяти. Примерами могут быть единичные числа
(например, 7, которое имеет значение 7) или выражения (например, 3 + х,
которое имеет значение х плюс 3).
Вот несколько примеров операций присваивания с использованием r- values:
Листинг 3.6.
1 |
int a |
// объявляем целочисленную переменную a |
|||||
|
|
|
|
|
|
|
|
2 |
a = 5 |
// |
5 |
имеет значение |
5, |
которое |
затем |
присваивается переменной а |
|
|
|||||
|
|
|
|
||||
|
|
|
|
|
|
|
|
3 |
a = 4 + 6 |
// |
4 |
+ 6 имеет значение |
10, |
которое |
затем |
присваивается переменной а |
|
|
|||||
|
|
|
|
||||
|
|
|
|||||
4 |
int b |
// объявляем целочисленную переменную b |
|||||
|
|
|
|||||
|
|
// a имеет значение 10 (исходя из предыдущих |
|||||
5 |
b = a |
операций), которое затем присваивается |
|||||
|
|
переменной b |
|
|
|
||
|
|
|
|
|
|
|
|
10