Размеры типов данных с в битах. Сколько «весят» типы данных

Размеры типов данных с в битах. Сколько «весят» типы данных

Целый тип char занимает в памяти 1 байт (8 бит) и позволяет выразить в двоичной системе счисления 2^8 значений=256. Тип char может содержать как положительные, так и отрицательные значения. Диапазон изменения значений составляет от -128 до 127.

uchar

Целый тип uchar также занимает в памяти 1 байт, как и тип char, но в отличие от него, uchar предназначен только для положительных значений. Минимальное значение равно нулю, максимальное значение равно 255. Первая буква u в названии типа uchar является сокращением слова unsigned (беззнаковый).

short

Целый тип short имеет размер 2 байта(16 бит) и, соответственно, позволяет выразить множество значений равное 2 в степени 16: 2^16=65 536. Так как тип short является знаковым и содержит как положительные, так и отрицательные значения, то диапазон значений находится между -32 768 и 32 767.

ushort

Беззнаковым типом short является тип ushort, который также имеет размер 2 байта. Минимальное значение равно 0, максимальное значение 65 535.

int

Целый тип int имеет размер 4 байта (32 бита). Минимальное значение -2 147 483 648, максимальное значение 2 147 483 647.

uint

Беззнаковый целый тип uint занимает в памяти 4 байта и позволяет выражать целочисленные значения от 0 до 4 294 967 295.

long

Целый тип long имеет размер 8 байт (64 бита). Минимальное значение -9 223 372 036 854 775 808, максимальное значение 9 223 372 036 854 775 807.

ulong

Целый тип ulong также занимает 8 байт и позволяет хранить значения от 0 до 18 446 744 073 709 551 615.

Примеры:

char ch= 12 ;
short sh=- 5000 ;
int in= 2445777 ;

Так как беззнаковые целые типы не предназначены для хранения отрицательных значений, то попытка установить отрицательное значение может привести к неожиданным последствиям. Вот такой невинный скрипт приведет к бесконечному циклу:

Правильно будет так:

Результат:

Ch= -128 u_ch= 128
ch= -127 u_ch= 129
ch= -126 u_ch= 130
ch= -125 u_ch= 131
ch= -124 u_ch= 132
ch= -123 u_ch= 133
ch= -122 u_ch= 134
ch= -121 u_ch= 135
ch= -120 u_ch= 136
ch= -119 u_ch= 137
ch= -118 u_ch= 138
ch= -117 u_ch= 139
ch= -116 u_ch= 140
ch= -115 u_ch= 141
ch= -114 u_ch= 142
ch= -113 u_ch= 143
ch= -112 u_ch= 144
ch= -111 u_ch= 145
...

В этом уроке мы рассмотрим целочисленные типы данных, их диапазоны значений, деление, а также переполнение: что это такое и примеры.

Целочисленные типы данных

Целочисленный тип данных - это тип, переменные которого могут содержать только целые числа (без дробной части, например: -2, -1, 0, 1, 2). В C++ есть пять основных целочисленных типов, доступных для использования:

Примечание : Тип char — это особый случай, он является как целочисленным, так и символьным типом данных. Об этом детальнее мы поговорим в одном из следующих уроков.

Основным различием между целочисленными типами выше является их , чем он больше, тем больше значений сможет хранить переменная этого типа.

Определение целочисленных переменных

Происходит следующим образом:

char c; short int si; // допустимо short s; // предпочтительнее int i; long int li; // допустимо long l; // предпочтительнее long long int lli; // допустимо long long ll; // предпочтительнее

В то время как полные названия short int , long int и long long int могут использоваться, их сокращённые версии (без int) более предпочтительны для использования. К тому же постоянное добавление int затрудняет чтение кода (легко спутать с переменной).

Диапазоны значений и знак целочисленных типов данных

Как вы уже знаете из предыдущего урока, переменная с n-ным количеством бит может хранить 2 n возможных значений. Но что это за значения? Те, которые находятся в диапазоне. Диапазон - это значения от и до, которые может хранить определённый тип данных. Диапазон целочисленной переменной определяется двумя факторами: её размером (в битах) и её знаком (который может быть signed или unsigned ).

Целочисленный тип signed (со знаком ) означает, что переменная может содержать как положительные, так и отрицательные числа. Чтобы объявить переменную как signed, используйте ключевое слово signed:

signed char c; signed short s; signed int i; signed long l; signed long long ll;

signed char c ;

signed short s ;

signed int i ;

signed long l ;

signed long long ll ;

По умолчанию, ключевое слово signed пишется перед типом данных.

1-байтовая целочисленная переменная со знаком (signed) имеет диапазон значений от -128 до 127. Любое значение от -128 до 127 (включительно) может храниться в ней безопасно.

В некоторых случаях мы можем заранее знать, что отрицательные числа в программе использоваться не будут. Это очень часто встречается при использовании переменных для хранения количества или размера чего-либо (например, ваш рост или вес не может быть отрицательным).

Целочисленный тип unsigned (без знака ) может содержать только положительные числа. Чтобы объявить переменную как unsigned , используйте ключевое слово unsigned:

unsigned char c; unsigned short s; unsigned int i; unsigned long l; unsigned long long ll;

unsigned char c ;

unsigned short s ;

unsigned int i ;

unsigned long l ;

unsigned long long ll ;

1-байтовая целочисленная переменная без знака (unsigned) имеет диапазон значений от 0 до 255.

Обратите внимание, объявление переменной как unsigned означает, что она не сможет содержать отрицательные числа (только положительные).

Теперь, когда вы поняли разницу между signed и unsigned, давайте рассмотрим диапазоны значений разных типов данных:

Размер/Тип Диапазон значений
1 байт signed от -128 до 127
1 байт unsigned от 0 до 255
2 байта signed от -32 768 до 32 767
2 байта unsigned от 0 до 65 535
4 байта signed от -2 147 483 648 до 2 147 483 647
4 байта unsigned от 0 до 4 294 967 295
8 байтов signed от -9 223 372 036 854 775 808 до 9 223 372 036 854 775 807
8 байтов unsigned от 0 до 18 446 744 073 709 551 615

Для математиков : переменная signed с n-ным количеством бит имеет диапазон от -(2 n-1) до 2 n-1 -1. Переменная unsigned с n-ным количеством бит имеет диапазон от 0 до (2 n)-1. Для нематематиков: используем таблицу 🙂

Начинающие программисты иногда путаются между signed и unsigned переменными. Но есть простой способ запомнить их различия. Чем отличается отрицательное число от положительного? Правильно! Минусом спереди. Если минуса нет, значит число — положительное. Следовательно, целочисленный тип со знаком (signed) означает, что минус может присутствовать, т.е. числа могут быть как положительными, так и отрицательными. Целочисленный тип без знака (unsigned) означает, что минус спереди полностью отсутствует, т.е. числа могут быть только положительными.

Что используется по умолчанию: signed или unsigned?

Так что же произойдёт, если мы объявим переменную без указания signed или unsigned?

Все целочисленные типы данных, кроме char, являются signed по умолчанию. Тип char может быть как signed, так и unsigned (но, обычно, signed).

В большинстве случаев ключевое слово signed не пишется (оно и так используется по умолчанию), за исключением типа char (здесь лучше уточнить).

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

Правило: Используйте целочисленные типы signed, вместо unsigned .

Переполнение

Вопрос: «Что произойдёт, если мы попытаемся использовать значение, которое находится вне диапазона значений определённого типа данных?». Ответ: «Переполнение».

Переполнение (англ. «overflow» ) случается при потере бит из-за того, что переменной не было выделено достаточно памяти для их хранения.

Примеры переполнения

Рассмотрим переменную unsigned, которая состоит из 4 битов. Любое из двоичных чисел, перечисленных в таблице выше, поместиться внутри этой переменной.

«Но что произойдёт, если мы попытаемся присвоить значение, которое занимает больше 4 битов?». Правильно! Переполнение. Наша переменная будет хранить только 4 наименее значимых (те, что справа) бита, все остальные — потеряются.

Например, если мы попытаемся поместить число 21 в нашу 4-битную переменную:

Десятичная система Двоичная система
21 10101

Число 21 занимает 5 бит (10101). 4 бита справа (0101) поместятся в переменную, а крайний левый бит (1) просто потеряется. Т.е. наша переменная будет содержать 0101, что равно 101 (нуль спереди не считается), а это уже число 5, а не 21.

Примечание : О конвертации чисел из двоичной системы в десятичную и наоборот будет отдельный урок, где мы всё детально рассмотрим и обсудим.

Теперь рассмотрим пример в коде (тип short занимает 16 бит):

#include int main() { unsigned short x = 65535; // наибольшее значение, которое может хранить 16-битная unsigned переменная std::cout << "x was: " << x << std::endl; x = x + 1; // 65536 - это число больше максимально допустимого числа из диапазона допустимых значений. Следовательно, произойдёт переполнение, так как переменнная x не может хранить 17 бит std::cout << "x is now: " << x << std::endl; return 0; }

#include

int main ()

unsigned short x = 65535 ; // наибольшее значение, которое может хранить 16-битная unsigned переменная

std :: cout << "x was: " << x << std :: endl ;

x = x + 1 ; // 65536 - это число больше максимально допустимого числа из диапазона допустимых значений. Следовательно, произойдёт переполнение, так как переменнная x не может хранить 17 бит

std :: cout << "x is now: " << x << std :: endl ;

return 0 ;

x was: 65535
x is now: 0

Что случилось? Произошло переполнение, так как мы попытались впихнуть невпихуемое в переменную x .

Для тех, кто хочет знать больше: Число 65 535 в двоичной системе счисления представлено как 1111 1111 1111 1111. 65 535 - это наибольшее число, которое может хранить 2-байтовая (16 бит) целочисленная переменная без знака, так как это число использует все 16 бит. Когда мы добавляем 1, то получаем число 65 536. Число 65 536 представлено в двоичной системе как 1 0000 0000 0000 0000, и занимает 17 бит! Следовательно, самый главный бит (которым является 1) теряется, а все 16 бит справа — остаются. Комбинация 0000 0000 0000 0000 соответствует десятичному 0, что и является нашим результатом.

Аналогичным образом, мы получим переполнение, использовав число, меньше минимального из диапазона допустимых значений:

#include int main() { unsigned short x = 0; // наименьшее значение, которое 2-байтовая unsigned переменная может хранить std::cout << "x was: " << x << std::endl; x = x - 1; // переполнение! std::cout << "x is now: " << x << std::endl; return 0; }

#include

int main ()

unsigned short x = 0 ; // наименьшее значение, которое 2-байтовая unsigned переменная может хранить

std :: cout << "x was: " << x << std :: endl ;

x = x - 1 ; // переполнение!

std :: cout << "x is now: " << x << std :: endl ;

return 0 ;

Результат выполнения программы выше:

x was: 0
x is now: 65535

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

В этой записи-шпаргалке приведены сведения об основных типах данных языка программирования C++ и особенности их реализации. Также, в конце записи составлена таблица с диапазонами значений этих типов.

Концепция типа данных

Основная цель любой программы состоит в обработке данных. Данные различного типа хранятся и обрабатываются по-разному. В любом алгоритмическом языке каждая константа, переменная, результат вычисления выражения или функции должны иметь определенный тип.

Тип данных определяет:

  • внутреннее представление данных в памяти компьютера;
  • множество значений, которые могут принимать величины этого типа;
  • операции и функции, которые можно применять к величинам этого тина.

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

Все типы языка C++ можно разделить на основные и составные . В языке C++ определено шесть основных типов данных для представления целых, вещественных, символьных и логических величин. На основе этих типов программист может вводить описание составных типов. К ним относятся массивы, перечисления, функции, структуры, ссылки, указатели, объединения и классы.

Основные типы данных в C++

Основные (стандартные) типы данных часто называют арифметическими, поскольку их можно использовать в арифметических операциях. Для описания основных типов определены следующие :

  1. int (целый);
  2. char (символьный);
  3. wchar_t (расширенный символьный);
  4. bool (логический);
  5. float (вещественный);
  6. double (вещественный с двойной точностью).

Первые четыре тина называют целочисленными (целыми ), последние два - типами с плавающей точкой . Код, который формирует компилятор для обработки целых величин, отличается от кода для величин с плавающей точкой.

Существует четыре спецификатора типа , уточняющих внутреннее представление и диапазон значений стандартных типов:

  • short (короткий);
  • long (длинный);
  • signed (знаковый);
  • unsigned (беззнаковый).

Целый тип (int)

Размер типа int не определяется стандартом, а зависит от компьютера и компилятора. Для 16-разрядного процессора под величины этого типа отводится 2 байта, для 32-разрядного - 4 байта.

Спецификатор short перед именем типа указывает компилятору, что под число требуется отвести 2 байта независимо от разрядности процессора. Спецификатор long означает, что целая величина будет занимать 4 байта. Таким образом, на 16-разрядном компьютере эквиваленты int и short int, а на 32-разрядном - int и long int.

Внутреннее представление величины целого типа - целое число в двоичном коде. При использовании спецификатора signed старший бит числа интерпретируется как знаковый (0 - положительное число, 1 - отрицательное). Спецификатор unsigned позволяет представлять только положительные числа, поскольку старший разряд рассматривается как часть кода числа. Таким образом, диапазон значений типа int зависит от спецификаторов. Диапазоны значений величин целого типа с различными спецификаторами для IBM PC-совместимых компьютеров приведены в таблице «Диапазоны значений простых типов данных» в конце записи.

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

Константам, встречающимся в программе, приписывается тот или иной тип в соответствии с их видом. Если этот тип по каким-либо причинам не устраивает программиста, он может явно указать требуемый тип с помощью суффиксов L, l (long) и U, u (unsigned). Например, константа 32L будет иметь тип long и занимать 4 байта. Можно использовать суффиксы L и U одновременно, например, 0x22UL или 05Lu.

Примечание

Типы short int, long int, signed int и unsigned int можно сокращать до short, long, signed и unsigned соответственно.

Символьный тип (char)

Под величину символьного типа отводится количество байт, достаточное для размещения любого символа из набора символов для данного компьютера, что и обусловило название типа. Как правило, это 1 байт. Тип char, как и другие целые типы, может быть со знаком или без знака. В величинах со знаком можно хранить значения в диапазоне от -128 до 127. При использовании спецификатора unsigned значения могут находиться в пределах от О до 255. Этого достаточно для хранения любого символа из 256-символьного набора ASCII. Величины типа char применяются также для хранения целых чисел, не превышающих границы указанных диапазонов.

Расширенный символьный тип (wchar_t)

Тип wchar_t предназначен для работы с набором символов, для кодировки которых недостаточно 1 байта, например, Unicode. Размер этого типа зависит от реализации; как правило, он соответствует типу short. Строковые константы типа wchar_t записываются с префиксом L, например, L»Gates».

Логический тип (bool)

Величины логического типа могут принимать только значения true и false, являющиеся зарезервированными словами. Внутренняя форма представления значения false - 0 (нуль). Любое другое значение интерпретируется как true. При преобразовании к целому типу true имеет значение 1.

Типы с плавающей точкой (float, double и long double)

Стандарт C++ определяет три типа данных для хранения вещественных значений: float, double и long double.

Типы данных с плавающей точкой хранятся в памяти компьютера иначе, чем целочисленные. Внутреннее представление вещественного числа состоит из двух частей - мантиссы и порядка. В IBM PC-совместимых компьютерах величины типа float занимают 4 байта, из которых один двоичный разряд отводится под знак мантиссы, 8 разрядов под порядок и 23 под мантиссу. Мантисса - это число, большее 1.0, но меньшее 2.0. Поскольку старшая цифра мантиссы всегда равна 1, она не хранится.

Для величин типа double, занимающих 8 байт, под порядок и мантиссу отводится 11 и 52 разряда соответственно. Длина мантиссы определяет точность числа, а длина порядка - его диапазон. Как можно видеть из таблицы в конце записи, при одинаковом количестве байт, отводимом под величины типа float и long int, диапазоны их допустимых значений сильно различаются из-за внутренней формы представления .

Спецификатор long перед именем типа double указывает, что под его величину отводится 10 байт.

Константы с плавающей точкой имеют по умолчанию тип double. Можно явно указать тип константы с помощью суффиксов F, f (float) и L, l (long). Например, константа 2E+6L будет иметь тип long double, а константа 1.82f - тип float.

Для написания переносимых на различные платформы программ нельзя делать предположений о размере типа int. Для его получения необходимо пользоваться операцией sizeof, результатом которой является размер типа в байтах. Например, для операционной системы MS-DOS sizeof (int) даст в результате 2, а для Windows 98 или OS/2 результатом будет 4.

В стандарте ANSI диапазоны значений для основных типов не задаются, определяются только соотношения между их размерами, например:

sizeof(float) ≤ slzeof(double) ≤ sizeof(long double)
sizeof(char) ≤ slzeof(short) ≤ sizeof(int) ≤ sizeof(long)

Примечание

Минимальные и максимальные допустимые значения для целых типов зависят от реализации и приведены в заголовочном файле (), характеристики вещественных типов - в файле (), а также в шаблоне класса numeric_limits

Тип void

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

Диапазоны значений простых типов данных в C++ для IBM PC-совместимых компьютеров

Q: Что означает термин IBM PC-совместимый компьютер?
A: IBM PC-совместимый компьютер (англ. IBM PC compatible) - компьютер, архитектурно близкий к IBM PC, XT и AT. IBM PC-совместимые компьютеры построены на базе микропроцессоров, совместимых с Intel 8086 (а, как известно, все выпущенные позднее процессоры Intel имеют полную обратную совместимость с 8086). По сути это практически все современные компьютеры.

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

Тип Диапазон значений Размер (байт)
bool true и false 1
signed char -128 … 127 1
unsigned char 0 … 255 1
signed short int -32 768 … 32 767 2
unsigned short int 0 … 65 535 2
signed long int -2 147 483 648 … 2 147 483 647 4
unsigned long int 0 … 4 294 967 295 4
float 3.4e-38 … 3.4e+38 4
double 1.7e-308 … 1.7C+308 8
long double 3.4e-4932 … 3.4e+4932 10

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

Типом данных в программировании называют совокупность двух множеств: множество значений и множество операций, которые можно применять к ним. Например, к типу данных целых неотрицательных чисел, состоящего из конечного множества натуральных чисел, можно применить операции сложения (+), умножения (*), целочисленного деления (/), нахождения остатка (%) и вычитания (−).

Язык программирования, как правило, имеет набор примитивных типов данных - типы, предоставляемые языком программирования как базовая встроенная единица. В C++ такие типы создатель языка называет фундаментальными типами . Фундаментальными типами в C++ считаются:

  • логический (bool);
  • символьный (напр., char);
  • целый (напр., int);
  • с плавающей точкой (напр., float);
  • перечисления (определяется программистом);
  • void .

Поверх перечисленных строятся следующие типы:

  • указательные (напр., int*);
  • массивы (напр., char);
  • ссылочные (напр., double&);
  • другие структуры.

Перейдём к понятию литерала (напр., 1, 2.4F, 25e-4, ‘a’ и др.): литерал - запись в исходном коде программы, представляющаясобой фиксированное значение. Другими словами, литерал - это просто отображение объекта (значение) какого-либо типа в коде программы. В C++ есть возможность записи целочисленных значений, значений с плавающей точкой, символьных, булевых, строковых.

Литерал целого типа можно записать в:

  • 10-й системе счисления. Например, 1205 ;
  • 8-й системе счисления в формате 0 + число. Например, 0142 ;
  • 16-й системе счисления в формате 0x + число. Например, 0x2F .

24, 030, 0x18 - это всё записи одного и того же числа в разных системах счисления.
Для записи чисел с плавающей точкой используют запись через точку: 0.1, .5, 4. - либо в
экспоненциальной записи - 25e-100. Пробелов в такой записи быть не должно.

Имя, с которым мы можем связать записанные литералами значения, называют переменной. Переменная - это поименованная либо адресуемая иным способом область памяти, адрес которой можно использовать для доступа к данным. Эти данные записываются, переписываются и стираются в памяти определённым образом во время выполнения программы. Переменная позволяет в любой момент времени получить доступ к данным и при необходимости изменить их. Данные, которые можно получить по имени переменной, называют значением переменной.
Для того, чтобы использовать в программе переменную, её обязательно нужно объявить, а при необходимости можно определить (= инициализировать). Объявление переменной в тексте программы обязательно содержит 2 части: базовый тип и декларатор. Спецификатор и инициализатор являются необязательными частями:

Const int example = 3; // здесь const - спецификатор // int - базовый тип // example - имя переменной // = 3 - инициализатор.

Имя переменной является последовательностью символов из букв латинского алфавита (строчных и прописных), цифр и/или знака подчёркивания, однако первый символ цифрой быть не может . Имя переменной следует выбирать таким, чтобы всегда было легко догадаться о том, что она хранит, например, «monthPayment». В конспекте и на практиках мы будем использовать для правил записи переменных нотацию CamelCase. Имя переменной не может совпадать с зарезервированными в языке словами, примеры таких слов: if, while, function, goto, switch и др.

Декларатор кроме имени переменной может содержать дополнительные символы:

  • * - указатель; перед именем;
  • *const - константный указатель; перед именем;
  • & - ссылка; перед именем;
  • - массив; после имени;
  • () - функция; после имени.

Инициализатор позволяет определить для переменной её значение сразу после объявления. Инициализатор начинается с литерала равенства (=) и далее происходит процесс задания значения переменной. Вообще говоря, знак равенства в C++ обозначает операцию присваивания; с её помощью можно задавать и изменять значение переменной. Для разных типов он может быть разным.

Спецификатор задаёт дополнительные атрибуты, отличные от типа. Приведённый в примере спецификатор const позволяет запретить последующее изменение значение переменной. Такие неизменяемые переменные называют константными или константой.

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

Const int EMPTY_CONST; // ошибка, не инициализована константная переменная const int EXAMPLE = 2; // константа со значением 2 EXAMPLE = 3; // ошибка, попытка присвоить значение константной переменной

Для именования констант принято использовать только прописные буквы, разделяя слова символом нижнего подчёркивания.

Основные типы данных в C++

Разбирая каждый тип, читатель не должен забывать об определении типа данных.

1. Целочисленный тип (char, short (int), int, long (int), long long)

Из названия легко понять, что множество значений состоит из целых чисел. Также множество значений каждого из перечисленных типов может быть знаковым (signed) или беззнаковым (unsigned). Количество элементов, содержащееся в множестве, зависит от размера памяти, которая используется для хранения значения этого типа. Например, для переменной типа char отводится 1 байт памяти, поэтому всего элементов будет:

  • 2 8N = 2 8 * 1 = 256, где N - размер памяти в байтах для хранения значения

В таком случае диапазоны доступных целых чисел следующие:

  • - для беззнакового char
  • [-128..127] - для знакового char

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

Unsigned long values; // задаёт целый (длинный) беззнаковый тип.

Перечисленные типы отличаются только размерами памяти, которая требуется для хранения. Поскольку язык C++ достаточно машинно-зависимый стандарт языка лишь гарантирует выполнение следующего условия:

  • 1 = размер char ≤ размер short ≤ размер int ≤ размер long.

Обычно размеры типов следующие: char - 1, short - 2, int - 4, long -8, long long - 8 байт.

Со значениями целого типа можно совершать арифметические операции: +, -, *, /, %; операции сравнения: ==, !=, <=, <, >, >=; битовые операции: &, |, xor, <<, >>.
Большинство операций, таких как сложение, умножение, вычитание и операции сравнения, не вызывают проблем в понимании. Иногда, после выполнения арифметических операций, результат может оказаться за пределами диапазона значений; в этом случае программа выдаст ошибку.
Целочисленное деление (/) находит целую часть от деления одного целого числа, на другое. Например:

  • 6 / 4 = 1;
  • 2 / 5 = 0;
  • 8 / 2 = 4.

Символ процента (%) обозначает операцию определение остатка от деления двух целых чисел:

  • 6 % 4 = 2;
  • 10 % 3 = 1.

Более сложные для понимания операции - битовые: & (И), | (ИЛИ), xor (исключающее ИЛИ), << (побитовый сдвиг влево), >> (побитовый сдвиг вправо).

Битовые операции И, ИЛИ и XOR к каждому биту информации применяют соответствующую логическую операцию:

  • 1 10 = 01 2
  • 3 10 = 11 2
  • 1 10 & 3 10 = 01 2 & 11 2 = 01 2
  • 1 10 | 3 10 = 01 2 | 11 2 = 11 2
  • 1 10 xor 3 10 = 01 2 xor 11 2 = 10 2

В обработке изображения используют 3 канала для цвета: красный, синий и зелёный - плюс прозрачность, которые хранятся в переменной типа int, т.к. каждый канал имеет диапазон значений от 0 до 255. В 16-иричной системе счисления некоторое значение записывается следующим образом: 0x180013FF; тогда значение 18 16 соответствует красному каналу, 00 16 - синему, 13 16 - зелёному, FF - альфа-каналу (прозрачности). Чтобы выделить из такого целого числа определённый канал используют т.н. маску, где на интересующих нас позициях стоят F 16 или 1 2 . Т.е., чтобы выделить значение синего канала необходимо использовать маску, т.е. побитовое И:

Int blue_channel = 0x180013FF & 0x00FF0000;

После чего полученное значение сдвигается вправо на необходимое число бит.

Побитовый сдвиг смещает влево или вправо на столько двоичных разрядов числа, сколько указано в правой части операции. Например, число 39 для типа char в двоичном виде записывается в следующем виде: 00100111. Тогда:

Char binaryExample = 39; // 00100111 char result = binaryExample << 2; // сдвигаем 2 бита влево, результат: 10011100

Если переменная беззнакового типа, тогда результатом будет число 156, для знакового оно равно -100. Отметим, что для знаковых целых типов единица в старшем разряде битового представления - признак отрицательности числа. При этом значение, в двоичном виде состоящие из всех единиц соответствует -1; если же 1 только в старшем разряде, а в остальных разрядах - нули, тогда такое число имеет минимальное для конкретного типа значения: для char это -128.

2. Тип с плавающей точкой (float, double (float))

Множество значений типа с плавающей точкой является подмножеством вещественных чисел, но не каждое вещественное число представимо в двоичном виде, что приводит иногда к глупым ошибкам:

Float value = 0.2; value == 0.2; // ошибка, value здесь не будет равно 0.2.

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

Value - 0.2 < 1e-6; // ok, подбирать интервал тоже нужно осторожно

Помимо операций сравнения тип с плавающей точкой поддерживает 4 арифметические операции, которые полностью соответствуют математическим операциям с вещественными числами.

3. Булевый (логический) тип (bool)

Состоит всего из двух значений: true (правда) и false (ложь). Для работы с переменными данного типа используют логические операции: ! (НЕ), == (равенство), != (неравенство), && (логическое И), || (логическое ИЛИ). Результат каждой операции можно найти в соответствующей таблицы истинности. например:

X Y XOR 0 0 0 0 1 1 1 0 1 1 1 0

4. Символьный тип (char, wchar_t)

Тип char - не только целый тип (обычно, такой тип называют byte), но и символьный, хранящий номер символа из таблицы символом ASCII . Например код 0x41 соответствует символу ‘A’, а 0x71 - ‘t’.

Иногда возникает необходимость использования символов, которые не закреплены в таблицы ASCII и поэтому требует для хранения более 1-го байта. Для них существует широкий символ (wchar_t).

5.1. Массивы

Массивы позволяют хранить последовательный набор однотипных элементов. Массив хранится в памяти непрерывным блоком, поэтому нельзя объявить массив, не указав его размер . Чтобы объявить массив после имени переменной пишут квадратные скобки () с указанием его размера. Например:

Int myArray; // Массив из 5-и элементов целого типа

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

Int odds = {1, 3, 7, 9, 11}; // Массив инициализируется 5-ю значениями

Для доступа к определённому значению в массиве (элемента массива) используют операцию доступа по индексу () с указанием номера элемента (номера начинаются с 0). Например:

Odds; // доступ к первому элементу массива. Вернёт значение 1 odds; // доступ к третьему элементу. Вернёт значение 7 odds = 13; // 5-му элементу массива присваиваем новое значение odds; // ошибка доступа

5.3. Строки

Для записи строки программисты используют идею, что строка - последовательный ряд (массив) символов. Для идентификации конца строки используют специальный символ конца строки: ‘\0’. Такие специальные символы, состоящие из обратного слэша и идентифицирующего символа, называют управляющими или escape-символами. Ещё существуют, например, ‘\n’ - начало новой строки, ‘\t’ - табуляция. Для записи в строке обратного слэша применяют экранирование - перед самим знаком ставят ещё один слэш: ‘\’. Экранирование также применяют для записи кавычек.

Создадим переменную строки:

Char textExample = {‘T’, ‘e’, ‘s’, ‘t’, ‘\0’}; // записана строка «Test»

Существует упрощённая запись инициализации строки:

Char textExample = “Test”; // Последний символ не пишется, но размер всё ещё 5

Не вдаваясь в подробности, приведём ещё один полезный тип данных - string. Строки
такого типа можно, например, складывать:

String hello = "Привет, "; string name = "Макс!"; string hello_name = hello + name; // Получится строка «Привет, Макс!»

6. Ссылка

Int a = 2; // переменная «a» указывает на значение 2 int &b = a; // переменная «b» указывает туда же, куда и «a» b = 4; // меняя значение b, программист меняет значение a. Теперь a = 4 int &c = 4; // ошибка, так делать нельзя, т.к. ссылка нельзя присвоить значение

7. Указатель

Чтобы разобраться с этим типом данных, необходимо запомнить, что множество значений этого типа - адреса ячеек памяти, откуда начинаются данные. Также указатель поддерживает операции сложения (+), вычитания (-) и разыменовывания (*).

Адреса 0x0 означает, что указатель пуст, т.е. не указывает ни на какие данные. Этот адрес имеет свой литерал - NULL:

Int *nullPtr = NULL; // пустой указатель

Сложение и вычитание адреса с целым числом или другим адресом позволяет
передвигаться по памяти, доступной программе.

Операция получения данных, начинающихся по адресу, хранящемуся в указателе, называется разыменовывания (*). Программа считывает необходимое количество ячеек памяти и возвращает значение, хранимое в памяти.

Int valueInMemory = 2; // задаём переменну целого типа int *somePtr = &valueIntMemory; // копируем адрес переменной, здесь & - возвращает адрес переменной somePtr; // адрес ячейки памяти, например, 0x2F *somePtr; // значение хранится в 4-х ячейках: 0x2F, 0x30, 0x31 и 0x32

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

Сам указатель хранится в памяти, как и значения переменных других типов, и занимает 4 байта, поэтому можно создать указатель на указатель.

8. Перечисления

Перечисления единственный базовый тип, задаваемый программистом. По большому счёту перечисление - упорядоченный набор именованных целочисленных констант, при этом имя перечисления будет базовым типом.

Enum color {RED, BLUE, GREEN};

По умолчанию, RED = 0, BLUE = 1, GREEN = 2. Поэтому значения можно сравнивать между собой, т.е. RED < BLUE < GREEN. Программист при объявлении перечисления может самостоятельно задать значения каждой из констант:

Enum access {READ = 1, WRITE = 2, EXEC = 4};

Часто удобно использовать перечисления, значения которых являются степенью двойки, т.к. в двоичном представлении число, являющееся степенью 2-и, будет состоять из 1-й единицы и нулей. Например:

8 10 = 00001000 2

Результат сложения этих чисел между собой всегда однозначно указывает на то, какие числа складывались:

37 10 = 00100101 2 = 00000001 2 + 00000100 2 + 00100000 2 = 1 10 + 4 10 + 32 10

Void

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

Void object; // ошибка, не существует объектов типа void void &reference; // ошибка, не существует ссылов на void void *ptr; // ok, храним указатель на неизвестный тип

Часто мы будем использовать void именно для обозначения того, что функция не возвращает никакого значения. С указателем типа void работают, когда программист берёт полностью на себя заботу о целостности памяти и правильном приведении типа.

Приведение типов

Часто бывает необходимо привести значение переменной одного типа к другому. В случае, когда множество значений исходного типа является подмножеством большего типа (например, int является подмножеством long, а long - double), компилятор способен неявно (implicitly ) изменить тип значения.

Int integer = 2; float floating = integer; // floating = 2.0

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

Существует возможность явного (explicitly) преобразования типов, для этого слева от переменной или какого-либо значения исходного типа в круглых скобках пишут тип, к которому будет произведено приведение:

Int value = (int) 2.5;

Унарные и бинарные операции

Те операции, которые мы выполняли ранее, называют бинарными: слева и справа от символа операции находятся значения или переменные, например, 2 + 3. В языках программирования помимо бинарных операций также используют унарные операции, которые применяются к переменным. Они могу находится как слева, так и справа от переменной, несколько таких операций встречались ранее - операция разыменовывания (*) и взятие адреса переменной (&) являются унарными. Операторы «++» и «—» увеличивают и уменьшают значение целочисленной переменной на 1 соответственно, причём могу писаться либо слева, либо справа от переменной.

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

A += 2; // то же самое, что и a = a + 2; b /= 5; // то же самое, что и b = b / 5; c &= 3; // то же самое, что и c = c & 3;

К данным относится любая информация, представленная в таком виде, который позволяет автоматизировать её сбор, хранение и обработку в ЭВМ (числа, символы, биты и др.).
Данные в программе могут быть исходными (задаваемыми на входе программы) или результатами обработки (промежуточными или выходными).
Все данные - переменные и константы - принадлежат определенному типу.
С каждым типом данных связан свой диапазон значений (количество байт под одно значение) и допустимые операции .

Типы данных в C/C++ разделяются на основные и производные .
К основным типам относят:

  1. void (пустой тип),
  2. int (целый тип),
  3. float (вещественные числа с плавающей точкой),
  4. double (вещественные числа с плавающей точкой двойной точности),
  5. char (символьный тип),
  6. bool - логический.

Составные типы

Для формирования других типов данных используют основные типы + так называемые спецификаторы . Типы данных, созданные на базе стандартных типов с использованием спецификаторов, называют составными типами данных . В C++ определены четыре спецификатора типов данных:
  1. short - короткий;
  2. long - длинный;
  3. signed-знаковый;
  4. unsigned-беззнаковый.
Производные типы – это:
  • массивы,
  • функции,
  • классы,
  • указатели,
  • ссылки,
  • структуры,
  • объединения.

Символьный тип

Данные типа char в памяти компьютера всегда занимают 1 байт. Это связа­но с тем, что обычно под величину символьного типа отводят столько памяти, сколько необходимо для хранения любого из 256 символов клавиатуры.
Сим­вольный тип может быть со знаком или без знака .
В величинах со знаком signed char можно хранить значения в диапазоне от -128 до 127. Соответствен­но значения переменных типа unsigned char могут находиться в диапазоне от 0 до 255.
Тип данных Диапазон значений Размер
char -128...+127 1 байт
unsigned char 0...255 1 байт
signed char -128...127 1 байт

При работе с символьными данными нужно помнить, что если в выражении встречается одиночный символ , он должен быть заключен в одинарные кавычки . Последовательность символов, то есть строка, при использовании в выражени­ях заключается в двойные кавычки . Например: ‘F’ , ‘3’ , “Иван”, “235”

Целочисленный тип

Данные типа int в памяти компьютера могут занимать либо 2, 4 или 8 байт. Это зависит от разрядности процессора.
По умолчанию все целые типы считаются знаковыми, то есть спецификатор signed (знаковый) можно не указывать.
Спецификатор unsigned (беззнаковый) позволяет представлять только положительные числа.

Диапазоны значений целочисленных типов

Тип данных Диапазон значений Размер(байт)
int
signed int
signed long int
-2147483648 ... 2147483647 4
unsigned int
unsigned long int
0 ... 4294967295 4
short int
signed short int
-32768 ... 32767 2
unsigned short int 0... 65535 2
long long int \(-(2^{63}-1)...(2^{63}-1)\) 8
unsigned long
long int
\(0...(2^{64}-1)\) 8

Вещественный тип

Внутреннее представление вещественного числа в памяти компьютера отлича­ется от представления целого числа. Число с плавающей точкой представлено в экспоненциальной форме . $$\pm mE\pm p$$ где m - мантисса (целое или дробное число с десятичной точкой), р - порядок (целое число). Для того чтобы перевести чис­ло в экспоненциальной форме к обычному представлению с фиксированной точкой, необходимо мантиссу умножить на десять в степени порядок Например: \(-6.42E+2=-6,42*10^{2}\)

Диапазоны значений вещественных типов

Тип данных Диапазон значений Размер (байт)
float 3.4E-38 ... 3.4E+38 4
double 1.7E-308... 1.7E+308 8
long double 3.4E-4932 ... 3.4E+4932 10

Длина мантиссы определяет точность числа, а длина порядка его диапазон.
Данные типа float занимают 4 байт, из которых 1 двоичный разряд отводится под знак, 8 разрядов - под порядок и 23 - под мантиссу. По­-скольку старшая цифра мантиссы всегда равна 1, она не хранится.
Данные типа double занимают 8 байт, в них под порядок -11 разрядов и под мантиссу -52 разряда соответственно.
Спецификатор типа long перед именем типа double указывает, что под величину отводится 10 байт.

Логический тип

Переменная типа bool может принимать только два значения true (истина) или false (ложь). Любое значение, не равное нулю, интерпретируется как true, а при преобразовании к целому типу принимает значение, равное 1. Значение false представлено в памяти как 0.

Тип void (пустой)

Множество значений этого типа пусто.
Тип void используется для:
  • определения фун­кций, которые не возвращают значения;
  • для указания пустого списка аргумен­тов функции;
  • как базовый тип для указателей;
  • в операции приведения типов.

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

Переменная - это поименованный участок памяти, в котором хранится значение определенного типа.
У переменной есть имя (идентификатор) и значение .
Имя служит для обращения к области памяти, в которой хранится значение.
Имя (идентификатор) - это совокупность букв, цифр и знаков подчёркивания, задающая имя переменной, название функции или ключевое слово в программе. Язык С/C++ чувствителен к регистру (т.е. Sum и sum будут восприниматься как две разные переменные).
где, тип – ключевое слово, определяющее объём памяти (число байтов), выделенный для хранения значения переменной (как объекта программы), (int – целый, float, double – вещественный, char – символьный, bool - логический);
имя – уникальный идентификатор переменной, задающий символический адрес объекта программы в памяти ЭВМ;
инициатор – начальное значение переменной, которое может отсутствовать в описании.
Например: Однотипные переменные можно сгруппировать, разделив «,». Описание переменных разного типа разделяется « ; ».
По месту обьявления переменные в языке С/С++ можно разделить на три класса:
  1. локальные- объяв­ляются внутри функции и доступны только в ней;
  2. глобальные - описываются до всех функций и доступны из любо­го места программы;
  3. формальные параметры функций описываются в списке параметров функции.
Пример: