Встроенные типы данных
❗ Оставлять переменные неициализированными float z;
является плохим тоном, поскольку до того как ей присвоят значение никто не знает что в ней лежит (мусор который лежит в памяти по присвоенному ей адресу) и к каким последствиям приведет обращение к ней.
❗ Стоит отметить, что неинициализированные глобальные переменные всегда будут заполнены нулями, в отличии от локальных, которые хранят мусор до инициализации. (Ссылаясь на язык АСМ, так происходит потому что глобальные переменные с заданным начальным значением, располагаются в секции .data, а неинициализированные в секции .bss, а при загрузке исполняемого файла в память, ОС заполняет нулями всю область .bss)
❗ Что касается локальных переменных, они располагаются в стековых фреймах, которые создаются при вызове функции и уничтожаются при её завершении. Очищать стековые фреймы весьма дорого (приходилось бы заполнять нулями миллионы раз), поэтому никто этого не делает, в отличии от .bss, которая зануляется один раз.
Тип | Размер | Описание |
---|---|---|
Логический | ||
bool | 1 байт | размер зависит от архитектуры и компилятора. 0 - false, все остальное - true |
Целочисленный (символьный) | ||
char | 1 байт | самый маленький (по размеру) тип, по стандарту равен размеру минимально адресуемой ячейке |
Целочисленный | ||
short int | 2 байта | |
int | 2/4 байта | размер зависит от архитектуры и компилятора, в основном 4 байта, однако в стандарте указано, что short <= int <= long |
long int | 4/8 байта | размер зависит от архитектуры и компилятора, действует соглашение (вне стандарта), что long должно хватать для представления указателей |
long long int | 8 байт | С плавающей точкой (IEEE-754) |
float | 4 байта | точность: 7 значащих цифр |
double | 8 байт | точность: 15 значащих цифр. С этим типом работают почти все математические функции из cmath, более того почти всегда в операциях float преобразуется в double, что делает использование float почти бессмысленным, кроме случаев когда нужно экономить память. |
long double | 10/12/16 байт | повышенная точность, float <= double <= long double, причем частенько размеры типов могут совпадать | Пустой |
void | В основном используют для функций, которые не возвращают значение и универсальных указателей. Создать переменную типа void нельзя |
short, long, unsigned, signed - называют модификаторами.
Все типы изначально являются signed (знаковые [могут принимать как отрицательные так и положительные значения]), в таком случае принимаемые ими значения будут лежать в диапазоне [-2⁽ⁿ⁻¹⁾ ; 2⁽ⁿ⁻¹⁾-1 ], где n - размер типа в битах.
❗ Является ли тип char изначально unsigned или signed зависит от компилятора.
Используя модификатор unsigned любой тип можно сделать беззнаковым (может принимать только положительные значения), тогда принимаемые им значения будут лежать в диапазоне [0 ; 2ⁿ-1 ], где n - размер типа в битах.
❗ Типы с плавающей запятой беззнаковыми не бывают.
❗ C++ предусматривает специальную возможность, для определения размеров любого типа на конкретной архитектуре и компиляторе - sizeof(тип/переменная)
❗ В большинстве ситуаций достаточно использовать float, а double только тогда, когда действительно необходима такая большая точность. Также используя float не стоит забывать добавлять к стандартным функциям постфикс f (например cosf), иначе будут лишние приведения.
Стоит отметить, что существуют некоторые сокращения:
- unsigned без ничего будет считаться unsigned int
- short без ничего будет считаться short int
- long без ничего будет считаться long int
Литералы
Литералы - значения, записанные в явном виде. Значения всех встроенных типов задаются литералами.
С++ позволяет записывать целые числа в десятичной, шестнадцатеричной и восьмеричной системах счисления:
- Число записано обычными арабскими цифрами - десятичная (29)
- Перед числом написан лидирующий ноль - восьмеричная (035 тоже самое, что и 29)
- Префикс 0х - шестнадцатиричная (0x1d или 0x1D тоже самое, что и 29)
❗ Восьмеричные и шестнадцатеричные литералы всегда беззнаковые, в то время как десятичные обычно рассматриваются как знаковые.
Если десятичный литерал умещается в разрядность типа int, то он будет считаться типа int, если нет, то unsigned int, если все еще нет то long, потом unsigned long, long long, unsigned long long и наконец ошибка. С восьмеричными и шестнадцатеричными литералами ситуация примерно такая же, только компилятор не пытается их делать signed.
Кроме, того при помощи суффиксов можно явным образом задать тип литерала:
- 42 - int
- 42L - long
- 42u - unsigned
- 42UL - unsigned long
- 3.14 - по умолчанию double
- 2.71F - делаем float
- 3.0E8 - 3.0 * 10⁸
- 4.2L - long (double)
- ‘a’ - символьный литерал (отметим что он типа int и равен коду символа - 97)
- Для служебных символов используются escape-последовательности (\n, \t, \v, \b, \a, \f)
- “Hello world” - строковый литерал
- ‘\0’ - нулевой символ, тоже самое что и 0, только для символьных литералов.
Забавное свойство, строку: “Hello” “world” компилятор преобразует в “Hello world” (можно использовать вместо “Hello \ world”, если не помещается все в одну строку (80 символов!))