Синтаксис имен переменных, венгерская нотация
Проблемы с использованием глобальных переменных
Безосновательное использование глобальных переменных обычно считается плохой практикой программирования.
Это связано с тем, что значение глобальной переменной может быть присвоено в любой функции, и это значение может оказаться непредсказуемым, в особенности если разные функциональные модули разрабатываются разными программистами группы или выполняются в разных потоках.
Концепция знаковых и беззнаковых целых чисел, самый старший бит
Беззнаковые целочисленные типы unsigned short, unsigned int, unsigned long и unsigned long long
Переполнение типов
Использование разделителя разрядов
Определение размера переменной с использованием оператора sizeof
Размер представляет собой объем памяти, резервируемый компилятором при объявлении программистом переменной для хранения присваиваемых ей данных.
Размер переменной зависит от ее типа, и в языке C++ есть очень удобный оператор sizeof, который возвращает размер переменной или типа в байтах.
Применение оператора sizeof очень простое. Чтобы определить размер целого числа, вызовите оператор sizeof с параметром в виде типа int:
cout << “Размер int: “ << sizeof (int);
Запрет сужающего преобразования при использовании инициализации списком
При инициализации переменной меньшего целочисленного типа (скажем, short) значением переменной большего типа (скажем, int) вы рискуете получить ошибку сужающего преобразования, при которой компилятор должен преобразовать значение, хранящееся в типе, который потенциально может содержать гораздо большие числа, в тип, который имеет меньшие размеры, например:
Чтобы избежать этой проблемы, C++11 рекомендует инициализацию списком, которая предотвращает сужение. Для использования этой возможности поместите значения или переменные инициализации в фигурные скобки { }. Синтаксис инициализации списком выглядит следующим образом:
Автоматический вывод типа с использованием auto
Использование ключевого слова typedef для замены типа
Язык C++ позволяет переименовывать типы переменных так, как вам кажется более удобным. Для этого используется ключевое слово typedef. Например, программист хочет назначить типу unsigned int более описательное имя STRICTLY_POSITIVE_INTEGER.
typedef unsigned int STRICTLY_POSITIVE_INTEGER;
STRICTLY_POSITIVE_INTEGER numEggsInBasket = 4532;
При компиляции первая строка указывает компилятору, что STRICLY_POSITIVE_INTEGER — это не что иное, как тип unsigned int. Впоследствии, когда компилятор встречает уже определенный тип STRICLY_POSITIVE_INTEGER, он заменяет его типом unsigned int и продолжает компиляцию.
Что такое константа
После того как значение константы определено, оно не может быть изменено. Попытки присваивания значения константе в языке C++ приводят к ошибке при компиляции.
Таким образом, в C++ константы похожи на переменные, за исключением того, что они не могут быть изменены. Подобно переменной, константа также занимает пространство в памяти и имеет имя для идентификации адреса выделенной для нее области. Однако содержимое этой области не может быть перезаписано. В языке C++ возможны следующие константы.
Литеральные константы
Литеральные константы могут быть многих типов — целочисленные, строки и т.д.
В нашей первой программе строка “Hello World” выводится с помощью следующей инструкции:
std : : cout << “Hello World” << std : : endl;
Здесь “Hello World” — это константа строкового литерала (string literal). Когда вы объявляете целое число наподобие
int someNumber = 10;
целочисленной переменной someNumber присваивается начальное значение, равное 10. Здесь 10 — это часть кода, компилируемая в приложение, которая является неизменной и тоже является литеральной константой (literal constant).
Объявление переменных как констант с использованием ключевого слова const
Самый важный тип констант C++ с практической и программной точек зрения объявляется с помощью ключевого слова const, расположенного перед типом переменной. В общем виде объявление выглядит следующим образом:
const имя_типа имя_константы = значение;
Хорошей практикой программирования является определение переменных, значения которых предполагаются неизменными, как констант. Применение ключевого слова const указывает, что программист позаботился об обеспечении неизменности данных и защищает свое приложение от непреднамеренных изменений этой константы. Это особенно полезно, когда над проектом работает несколько программистов.
Константы полезны при объявлении массивов постоянной длины, которые неизменны во время компиляции.
Объявление констант с использованием ключевого слова constexpr
Ключевое слово constexpr позволяет объявлять константы подобно функциям:
constexpr double GetPi( ) {return 3.1415926;}
Одно constexpr - выражение может использовать другое:
constexpr double TwicePi( ) {return 2 * GetPi( );}
GetPi( ) и TwicePi( ) могут казаться функциями, но это не совсем функции. Дело в том, что функции вызываются во время выполнения программы. Эти же константные выражения компилятор заменяет числом 3.141593 при каждом использовании GetPi( ) и числом 6.283186 при использовании TwicePi( ). Такое разрешение TwicePi( ) в константу увеличивает скорость выполнения программы по сравнению выполнением вычисления, содержащегося в функции.
Перечисления
Иногда некая переменная должна принимать значения только из определенного набора. Например, вы не хотите, чтобы среди цветов радуги случайно оказался бирюзовой или среди направлений компаса оказалось направление влево. В обоих этих случаях необходим тип переменной, значения которой ограничиваются определенным вами набором.
Перечисления (enumerations) — это именно то, что необходимо в данной ситуации. Перечисления объявляются с помощью ключевого слова enum.
Вот пример перечисления, которое определяет цвета радуги:
enum RainbowColors
{
Violet = 0,
Indigo,
Blue,
Green,
Yellow,
Orange,
Red
};
А вот другой пример — направления компаса:
enum CardinalDirections
{
North,
South,
East,
West
};
Перечисления используются как пользовательские. Переменные этого типа могут принимать значения, ограниченные объявленными ранее значениями перечисления. Так, при определении переменной, которая содержит цвет радуги, вы объявляете ее следующим образом:
RainbowColors MyWorldsColor = Blue; // Начальное значение
При объявлении перечисления компилятор преобразует его константы, такие как Violet и другие, в целые числа. Каждое последующее значение перечисления на единицу больше предыдущего. Начальное значение вы можете задать сами, но если вы этого не сделаете, компилятор начнет счет с 0. Так, значению North соответствует числовое значение 0.
По желанию можно также явно определить числовое значение напротив каждой из перечисляемых констант при их инициализации.
Определение констант с использованием директивы #define
Первое и главное: не используйте этот способ при написании новых программ.
Единственная причина упоминания определения констант с использованием директивы #define в этой книге — помочь вам понять некоторые устаревшие программы, в которых для определения числа к мог бы использоваться такой синтаксис:
#define pi 3.141593
Это макрокоманда препроцессора, предписывающая компилятору заменять все упоминания pi значением 3.141593 . Обратите внимание: это текстовая (читай: неинтеллектуальная) замена, осуществляемая препроцессором. Компилятор не знает фактический тип рассматриваемой константы и не заботится о нем.
Определение констант с использованием директивы препроцессора #define считается устаревшим и не рекомендуется.
Массивы (+ синтаксис), статические и динамические массивы, длина массива
int myNumbers[] = {2017, 2052, -525};
Объем памяти в байтах, резервируемой компилятором для массива?
В общем виде объем памяти в байтах, резервируемой компилятором для массива, составляет:
Байты массива = sizeof (Тип элемента) * Количество элементов
Доступ к данным, хранимым в массиве (ключевая проблема), переполнение буфера
Многомерные массивы
Доступ к элементам многомерного массива
Рассмотрим следующий массив:
int threeRowsThreeColumns [3] [3] = {{-501, 206, 2017}, {989, 101, 206}, {303, 456, 596}};
Он инициализирован так, что его можно рассматривать как три массива, каждый из которых содержит три целых числа. Здесь целочисленный элемент со значением 206 находится в позиции [0] [1], а элемент со значением 456 — в позиции [2] [1].
Строки символов в стиле С
std : : cout << “Hello World”;
char sayHello[] = {‘Н’,’е’,’l’,’l’,’о’,’ ‘,’W’,’о’,’г’,’l’,’d’,’\0’}
std : : cout << sayHello << std : : endl;
Строки C++: использование std : : string
Язык C++ предоставляет мощное и в то же время безопасное средство работы со
строками — класс s t d : : s tr in g . Класс s t d : : s tr in g не является статическим мас
сивом элементов типа char неизменного размера, как строки в стиле С, и допускает
увеличение размера, когда в нем необходимо сохранить больше данных.
Для использования строк C++ в код необходимо включить заголовочный
файл s trin g :
tin c lu d e < strin g >
Зачем заботиться об инициализации элементов статического массива?
Если не инициализировать массив, он будет содержать случайные и непредсказуемые значения, поскольку область занимаемой им памяти останется неизменной после последних операций. Инициализация массивов гарантирует, что находящая ся в нем информация будет иметь определенное и предсказуемое начальное состояние.