Переменные и типы

Полезность программ «Hello World», показанных в предыдущей главе, весьма сомнительна. Нам пришлось написать несколько строк кода, скомпилировать их, а затем выполнить полученную программу, просто чтобы получить результат простого предложения, написанного на экране. Конечно, было бы намного быстрее набирать выходное предложение.Однако программирование не ограничивается только печатью простых текстов на экране. Чтобы немного продвинуться дальше и стать способным писать программы, которые выполняют полезные задачи, которые действительно помогают нам работать, нам нужно ввести понятие переменных .Представим себе, что я прошу вас вспомнить номер 5, а затем я прошу вас также запомнить номер 2 одновременно. Вы только что сохранили два разных значения в вашей памяти (5 и 2). Теперь, если я попрошу вас добавить 1 к первому номеру, который я сказал, вы должны сохранить цифры 6 (это 5 + 1) и 2 в вашей памяти. Тогда мы могли бы, например, вычесть эти значения и получить результат 4.

Весь процесс, описанный выше, представляет собой сравнение того, что компьютер может делать с двумя переменными. Тот же процесс может быть выражен в C ++ со следующим набором операторов:

1
2
3
4
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это однобайтовый символ. Другие типы также предоставляются для более широких символов.
  • Численные целые типы: Они могут хранить целое числовое значение, например, 7или 1024. Они существуют в разных размерах и могут быть либо подписаны, либо без знака , в зависимости от того, поддерживают ли они отрицательные значения или нет.
  • Типы с плавающей точкой: они могут представлять реальные значения, например, 3.14или 0.01с разными уровнями точности, в зависимости от того, какой из трех типов с плавающей запятой используется.
  • Логический тип: логический тип, известный в C ++ as 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 longint Не меньше long. Не менее 64 бит.
Целочисленные типы (без знака) unsigned char (того же размера, что и их подписанные аналоги)
unsigned short int
unsigned int
unsigned long int
unsigned long longint
Типы с плавающей точкой float
double Точность не менее float
long double Точность не менее double
Булевский тип bool
Тип пустоты void нет хранения
Нулевой указатель decltype(nullptr)

* Имена некоторых целочисленных типов могут быть сокращены без их signedи intкомпонентов – для идентификации типа требуется только часть, не выделенная курсивом, часть, выделенная курсивом, является необязательной. То есть, может быть сокращенно , или просто ; все они определяют один и тот же фундаментальный тип. В каждой из вышеперечисленных групп разница между типами – это только их размер (т. Е. Сколько они занимают в памяти): первый тип в каждой группе является наименьшим, а последний является самым большим, причем каждый тип по крайней мере равен большой, как тот, который предшествует ему в той же группе. Кроме того, типы в группе имеют одинаковые свойства. Обратите внимание, что на панели выше, кромеsigned short intsigned shortshort intshort

char(который имеет размер точно одного байта), ни один из основных типов не имеет стандартного размера (но минимального размера не более). Поэтому тип не требуется (и во многих случаях нет) именно этот минимальный размер. Это не означает, что эти типы имеют неопределенный размер, но нет стандартного размера для всех компиляторов и машин; каждая реализация компилятора может указывать размеры для этих типов, которые наилучшим образом соответствуют архитектуре, в которой программа будет запущена. Эта довольно общая спецификация размеров для типов дает языку C ++ большую гибкость, чтобы адаптироваться для оптимальной работы на всех платформах, как существующих, так и будущих.

Типоразмерные размеры выражены в битах; чем больше бит имеет тип, тем более четкие значения он может представлять, но в то же время также потребляет больше места в памяти:

Размер Уникальные представляемые значения Заметки
8-разрядный 256 = 2 8
16-битный 65 536 = 2 16
32-битный 4 294 967 296 = 2 32 (~ 4 млрд)
64-битный 18 446 744 073 709 551 616 = 2 64 (~ 18 миллиардов миллиардов)

Для целочисленных типов, имеющих более представимые значения, означает, что диапазон значений, которые они могут представлять, больше; например, 16-разрядное целое число без знака могло бы представлять 65536 различных значений в диапазоне от 0 до 65535, тогда как его подписанный аналог мог бы представлять в большинстве случаев значения между -32768 и 32767. Отметим, что диапазон положительные значения примерно в два раза сокращены в виде подписанных типов по сравнению с неподписанными типами из-за того, что для знака используется один из 16 бит; это относительно скромная разница в диапазоне и редко оправдывает использование неподписанных типов, основанных исключительно на диапазоне положительных значений, которые они могут представлять.

Для типов с плавающей точкой размер влияет на их точность, имея больше или меньше бит для их значительного и экспоненциального значения.

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

Свойства основных типов в конкретной системе и реализации компилятора можно получить, используяnumeric_limitsклассов (см. стандартный заголовок <limits>). Если по какой-то причине требуются типы конкретных размеров, библиотека определяет определенные псевдонимы типа фиксированного размера в заголовке <cstdint>.

Типы, описанные выше (символы, целые числа, с плавающей точкой и логические), все вместе называются арифметическими типами. Но существуют два дополнительных фундаментальных типа:, voidкоторый идентифицирует отсутствие типа; и тип nullptr, который является специальным типом указателя. Оба типа будут обсуждаться далее в следующей главе о указателях.

C ++ поддерживает широкий спектр типов, основанных на основных типах, рассмотренных выше; эти другие типы известны как составные типы данных и являются одной из основных сильных сторон языка C ++. Мы также увидим их более подробно в будущих главах.

Объявление переменных

C ++ – это строго типизированный язык и требует, чтобы каждая переменная была объявлена ​​с ее типом до его первого использования. Это сообщает компилятору размер зарезервировать в памяти для переменной и как интерпретировать ее значение. Синтаксис объявления новой переменной в C ++ прост: мы просто пишем тип, за которым следует имя переменной (т. Е. Ее идентификатор). Например:

1
2
int a;
float mynumber;

Это две допустимые объявления переменных. Первая объявляет переменную типа intс идентификатором a. Второй объявляет переменную типа floatс идентификатором mynumber. После объявления переменные aи mynumberмогут использоваться в остальной части их области действия в программе.
Если объявление более одной переменной одного и того же типа, все они могут быть объявлены в одном выражении, разделив их идентификаторы запятыми. Например:

 
int a, b, c;

Это объявляет три переменные ( abи c), все из них типа int, и имеет то же значение, что и:

1
2
3
int a;
int b;
int c;

Чтобы увидеть, какие объявления переменных выглядят в действии внутри программы, давайте посмотрим на весь код C ++ примера вашей умственной памяти, предложенный в начале этой главы:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// operating with variables

#include <iostream>
using namespace std;

int main ()
{
  // declaring variables:
  int a, b;
  int result;

  // process:
  a = 5;
  b = 2;
  a = a + 1;
  result = a - b;

  // print out the result:
  cout << result;

  // terminate the program:
  return 0;
}
4

Не беспокойтесь, если что-то другое, чем сами декларации переменных, выглядят немного странно. Большая часть этого будет объяснена более подробно в следующих главах.

Инициализация переменных

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

В C ++ существует три способа инициализации переменных. Все они эквивалентны и напоминают эволюцию языка на протяжении многих лет:

первая, известная как c-подобная инициализация (потому что она унаследована от языка C), состоит из добавления знака равенства, за которым следует значение, которому переменная инициализируется:

type identifier = initial_value;
например, для объявления переменной типа, intназываемойx и инициализировать его до значения нуля с того же момента, когда он объявлен, мы можем написать:

 
int x = 0;

Второй метод, известный как инициализация конструктора (введенный языком C ++), включает начальное значение между круглыми скобками ( ()):

type identifier (initial_value);
Например:

 
int x (0);

Наконец, третий метод, известный как равномерная инициализация , аналогичен приведенному выше, но с использованием фигурных скобок ( {}) вместо круглых скобок (это было введено пересмотром стандарта C ++ в 2011 году):

type identifier {initial_value};
Например:

 
int x {0}; 

Все три способа инициализации переменных действительны и эквивалентны в C ++.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// initialization of variables

#include <iostream>
using namespace std;

int main ()
{
  int a=5;               // initial value: 5
  int b(3);              // initial value: 3
  int c{2};              // initial value: 2
  int result;            // initial value undetermined

  a = a + b;
  result = a - c;
  cout << result;

  return 0;
}
6

Тип вывода: auto и decltype

Когда инициализируется новая переменная, компилятор может определить, какой тип переменной автоматически инициализирует. Для этого достаточно использовать autoв качестве спецификатора типа для переменной:

1
2
int foo = 0;
auto bar = foo;  // the same as: int bar = foo; 

Здесь barобъявляется как имеющий autoтип; поэтому тип типа bar– это тип значения, используемого для его инициализации: в этом случае он использует тип foo, который есть int.

Переменные, которые не инициализируются, также могут использовать вычет типа с decltypeспецификатором:

1
2
int foo = 0;
decltype(foo) bar;  // the same as: int bar; 

Здесь barобъявлен как имеющий тот же тип, что и foo.

autoи decltypeявляются мощными функциями, недавно добавленными на язык. Но функции вывода типов, которые они вводят, предназначены для использования, когда тип не может быть получен другими способами или при его использовании улучшает читаемость кода. Два примера, приведенные выше, были, вероятно, ни одним из этих случаев использования. На самом деле они, вероятно, уменьшают читаемость, так как при чтении кода нужно искать тип, fooчтобы действительно знать тип bar.

Введение в строки

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

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

Первое отличие от основных типов данных заключается в том, что для объявления и использования объектов (переменных) этого типа программа должна включать заголовок, где тип определен в стандартной библиотеке (заголовке <string>):

1
2
3
4
5
6
7
8
9
10
11
12
// my first string
#include <iostream>
#include <string>
using namespace std;

int main ()
{
  string mystring;
  mystring = "This is a string";
  cout << mystring;
  return 0;
}
Это строка

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

1
2
3
string mystring = "This is a string";
string mystring ("This is a string");
string mystring {"This is a string"};

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// my first string
#include <iostream>
#include <string>
using namespace std;

int main ()
{
  string mystring;
  mystring = "This is the initial string content";
  cout << mystring << endl;
  mystring = "This is a different string content";
  cout << mystring << endl;
  return 0;
}
Это начальное строковое содержимое
Это другое строковое содержимое

Примечание: вставьте конецendl манипулятора в l (он печатает символ новой строки и промывает поток). 

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

Дополнительные сведения о стандартных строках C ++ см. В разделестрока класс ссылки.

Залишити відповідь