Сколько «весят» типы данных. Типы данных в языке си
Теги: С++ типы данных, auto, decltype, автоматический вывод типов
Типы данных
К ак и в си, переменные в С++ должны иметь валидное имя. То есть, состоять из чисел, букв и знака подчёркивания, не должны начинаться с цифры и не должны совпадать со служебными словами, которых теперь стало больше
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++ можно разбить на несколько групп
Знаковый тип. Переменные знакового типа могут использоваться для хранения одного символа. Самый простой тип char, размер которого равен 1 байт. Также имеются типы для представления знаков, размером больше одного байта
Вообще-то эти типы есть и в си, мы не останавливались подробно на изучении представления строк.
Целочисленные типы данных. Как и в си, могут обладать модификаторами signed и unsigned. Как и в си, основными типами являются char, int, long и long long. Ничего нового здесь не появилось.
Числа с плавающей точкой. Представлены типами float, double и long double. Ничего нового по сравнению с си.
Все описанные выше типы называют также арифметическими. Кроме них существует ещё пустой тип – void (также ничего нового по сравнению с си) и нулевой указатель. Теперь, вместо NULL с его удивительными свойствами, появился новый фундаментальный тип nullptr_t с единственным значением nullptr, который хранит нулевой указатель и равен только сам себе. При этом, он может быть приведён к нулевому указателю нужного типа.
В си++ введён булев тип. Он хранит всего два возможных значения true и false.
Си++ поддерживает также множество составных типов данных, которые будут рассмотрены позднее.
Объявление и инициализация переменных
В С++ переменные могут быть объявлены в любом месте внутри функции, а не только в самом начале блока кода В том числе, переменные могут быть объявлены и внутри цикла for.
Float a; float b; float sum; float step; a = 3.0f; b = 4.3f; sum = 0.0f; step = 0.05f; for (float i = a; i < b; i += step) { sum += i * i; } float mid = sum / (b - a) / step;
Инициализировать переменные можно при создании как в си
Int x = 0;
либо, используя конструктор
Int x(0); double d(3.2);
Кроме того, в С++ 2011 появилась т.н. uniform initialization, универсальная инициализация, которая позволяет использовать один синтаксис для инициализации любых объектов
Struct Point { int x; int y; }; struct Point position = { 3, 4 }; Point *pt = new Point{6, 8}; int length{5};
Вывод типов
В си++ 2011 служебное слово auto используется для автоматического определения типа переменных. Часто тип переменной может быть определён, исходя из правой части инициализации. В том случае, когда компилятор может однозначно определить тип, его можно задавать с помощью служебного слова auto:
Auto x = 3; //эквивалентно int x = 3; auto point = new Point; //эквивалентно Point *point = new Point
Кроме этого, есть возможность задавать тип переменной по уже имеющемуся типу, с помощью служебного слова decltype
Int intX = 42; decltype(intX) intY = 33; //эквивалентно int intY = 33; auto pt1 = new Point; decltype(pt1) p2 = new Point{2, 6}; //эквивалентно //Point *pt1 = new Point; //Point *pt2 = new Point{2, 6}
Строки
В С++ нет базового типа строка. Однако есть стандартная библиотека string, которая предоставляет класс для работы со строками.
#include
Со стандартной библиотекой string познакомимся поздее более подробно.
В этом уроке вы узнаете алфавит языка C++ , а также какие типы данных может обрабатывает программа на нем. Возможно, это не самый увлекательный момент, но эти знания необходимы!Кроме того, начав изучать любой другой язык программирования, Вы с большей уверенностью пройдете аналогичную стадию обучения. Программа на языке C++ может содержать следующие символы:
- прописные, строчные латинские буквы A, B, C…, x, y, z и знак подчеркивания;
- арабские цифры от 0 до 9;
- специальные знаки: { } , | , () + - / % * . \ ‘ : ? < > = ! & # ~ ; ^
- символы пробела, табуляции и перехода на новую строку.
В тесте программы можно использовать комментарии . Если текст с двух символов «косая черта» // и заканчивается символом перехода на новую строку или заключен между символами /* и */, то компилятор его игнорирует.
Данные в языке C++
Для решения задачи в любой программе выполняется обработка каких-либо данных. Они могут быть различных типов: целые и вещественные числа, символы, строки, массивы. Данные в языке C++ принято описывать в начале функции. К основным типам данных языка относят:
Для формирования других типов данных используют основные и так называемые спецификаторы. В C++ определенны четыре спецификатора типов данных:
- short - короткий;
- long - длинный;
- signed - знаковый;
- unsigned - беззнаковый.
Целочисленный тип
Переменная типа int в памяти компьютера может занимать либо 2, либо 4 байта. Это зависит разрядности процессора. По умолчанию все целые типы считаются знаковыми, то есть спецификатор signed можно не указывать. Спецификатор unsigned позволяет представлять только положительные числа. Ниже представлены некоторые диапазоны значений целого типа
Тип | Диапазон | Размер |
int | -2147483648…2147483647 | 4 байта |
unsigned int | 0…4294967295 | 4 байта |
signed int | -2147483648…2147483647 | 4 байта |
short int | -32768…32767 | 2 байта |
long int | -2147483648…2147483647 | 4 байта |
unsigned short int | 0…65535 | 2 байта |
Вещественный тип
Число с плавающей точкой представлено в форме mE +- p, где m - мантисса (целое или дробное число с десятичной точкой), p - порядок (целое число). Обычно величины типа float занимают 4 байта, а double 8 байт. Таблица диапазонов значений вещественного типа:
float | 3,4E-38…3,4E+38 | 4 байта |
double | 1,7E-308…1,7E+308 | 8 байт |
long double | 3,4E-4932…3,4E+4932 | 8 байт |
Логический тип
Переменная типа bool может принимать только два значения true (истина) или fasle (ложь). Любоезначение, не равное нулю, интерпретируется как true. Значение false представлено в памяти как 0.
Тип void
Множество значений этого типа пусто. Он используется для определения функций, которые не возвращают значения, для указания пустого списка аргументов функции, как базовый тип для указателей и в операции приведения типов.
Преобразование типов данных
В C++ различают два вида преобразования типов данных: явное и неявное.
- Неявное преобразование происходит автоматически. Это выполняется во время сравнения, присваивания или вычисления выражения различных типов. Например, следующая программа выведет на консоль значение типа float.
#include "stdafx.h"
#include
#include "stdafx.h" #include using namespace std ; int main () int i = 5 ; float f = 10.12 ; cout << i / f ; system ("pause>>void" ) ; return 0 ; |
Наивысший приоритет получает тот тип, при котором информация теряется менее всего. Не стоит злоупотреблять неявным преобразованием типов, так как могут возникнуть разного рода непредвиденные ситуации.
- Явное преобразование в отличие от неявного осуществляется программистом. Существует несколько способов такого преобразования:
- Преобразование в стили C : (float ) a
- Преобразование в стили C++ : float ()
Также приведения типов может осуществляться при помощи следующих операций:
static_cast <> () const_cast <> () reinterpret_cast <> () dynamic_cast <> ()
static_cast <> () const_cast <> () reinterpret_cast <> () dynamic_cast <> () |
static_cas - осуществляет преобразование связанных типов данных. Этот оператор приводит типы по обычным правилам, что может потребоваться в случае, когда компилятор не выполняет автоматическое преобразование. Синтаксис будет выглядеть так:
Тип static_cast <Тип> (объект);
С помощью static_cast нельзя убрать константность у переменной, но это по силам следующему оператору. const_cast - применяется только тогда, когда нужно снять константность у объекта. Синтаксис будет выглядеть следующим образом:
Тип const_cast < Тип > (объект );
reinterpret_cast - применяется для преобразования разных типов, целых к указателю и наоборот. Если вы увидели новое слово «указатель» - не пугайтесь! это тоже тип данных, но работать с ним Мы будем не скоро. Синтаксис тут такой же как, у ранее рассмотренных операторах:
Тип reinterpret _cast < Тип > (объект );
dynamic_cast - используется для динамического преобразования типов, реализует приведение указателей или ссылок. Синтаксис:
Тип dynamic _cast < Тип > (объект );
Управляющие символы
С некоторыми из этих самых «управляющих символов» Вы уже знакомы (например, с \n ). Все они начинаются с обратного «слеша», а также обрамляются двойными кавычками.
Изображение |
Шестнадцатеричный код |
Наименование |
Звуковой сигнал бипера |
||
Возврат на шаг |
||
Перевод страницы (формата) |
||
Перевод строки |
||
Возврат каретки |
||
Горизонтальная табуляция |
||
Вертикальная табуляция |
||
Типы данных в Си — класс данных, значения которых имеют схожие характеристики. Тип определяет внутреннее представление данных в памяти. Самые основные типы данных: логический, целочисленный, числа с плавающей точкой, строковые, указатели.
При динамической типизации переменная связывается с типом на момент инициализации. Получается, что переменная в разных участках кода может иметь разные типы. Динамическую типизацию поддерживают Java Script, Python, Ruby, PHP.
Статическая типизация является противоположностью динамической. При объявлении переменная получает тип, который не меняется в дальнейшем. Языки Си и Си++ являются именно такими. Этот способ наиболее удобный для написания сложного кода, а на стадии компиляции исключается много ошибок.
Языки неформально делятся на сильнотипизированный и слаботипизированный. Сильная типизация подразумевает, что компилятор выдаст ошибку при несовпадении ожидаемого и фактического типов.
x = 1 + “2”; //ошибка — нельзя прибавить к числу символьный знак
Пример слабой типизации.
Проверка согласования типов осуществляется системой типобезопасности. Ошибка типизации возникает, например, при попытке использовать число как функцию. Существуют нетипизированные языки. В противоположность типизированным, они позволяют осуществлять любые операции над каждым объектом.
Классы памяти
Переменные, независимо от их типа, имеют свою область видимости и время существования.
Классы памяти:
- auto;
- static;
- extern;
- register.
Все переменные в языке Си по умолчанию являются локальными. Они могут использоваться только внутри функции или блока. По завершении функции их значение уничтожается.
Статическая переменная также является локальной, но вне своего блока может иметь другое значение, а между вызовами функции значение сохраняется.
Внешняя переменная является глобальной. Она доступна в любой части кода и даже в другом файле.
Спецификаторы типов данных в Си могут не указываться в таких случаях:
- Все переменные внутри блока не являются переменными, соответственно, если предполагается использование именно этого класса памяти, то спецификатор auto не указывается.
- Все функции, объявленные вне блока или функции, являются по умолчанию глобальными, поэтому спецификатор extern не обязателен.
Для указания простых типов указываются спецификаторы int, char, float или double. К переменным могут подставляться модификаторы unsigned (беззнаковый), signed (знаковый), short, long, long long.
По умолчанию все числа являются знаковыми, соответственно, могут находиться в диапазоне только положительных чисел. Чтобы определить переменную типа char как знаковую, пишется signed char. Long, long long и short указывают, как много места в памяти отводится для хранения. Наибольшее — long long, наименьшее — short.
Char — самый маленький тип данных в Си. Для хранения значений выделяется всего 1 байт памяти. Переменной типа character обычно присваиваются символы, реже — цифры. Символьные значения берутся в кавычки.
Тип int хранит целые числа, его размер не определен — занимает до 4 байт памяти, в зависимости от архитектуры компьютера.
Явное преобразование беззнаковой переменной задается так:
Неявное выглядит так:
Float и double определяют числа с точкой. Числа float представляются в виде -2.3 или 3.34. Double используется для большей точности — после разделителя целой и дробной части указывается больше цифр. Этот тип занимает больше места в памяти, чем float.
Void имеет пустое значение. Он определяет функции, которые ничего не возвращают. С помощью этого спецификатора указывается пустое значение в аргументах методов. Указатели, которые могут принимать любой тип данных, также определяются как void.
Логический тип Bool
Применяется в проверках условий и циклах. Имеет всего два значения:
- истина;
- ложь.
Булевые значения могут преобразовываться в значение типа int. True эквивалентно единице, false — нулю. Преобразование типов предусмотрено только между bool и int, в противном случае компилятор выдаст ошибку.
if (x) { //Error: «Cannot implicitly convert type ‘int’ to ‘bool"»
if (x != 0) // The C# way
Строки и массивы
Массивы относятся к сложными типам даным в Си. ЯП не работает со строками так же, как это делает Джаваскрипт или Руби. В Си все строки являются массивами элементов символьного значения. Строки оканчиваются нулевым байтом “
Все данные в языке Си имеют свой тип. Переменные определенных типов занимают в памяти какое-то место, разное в зависимости от типа. В Си нет четкого закрепления количества памяти за определенными типами. Это отдано на реализацию конкретного компилятора под конкретную платформу. Например, переменная типа int в одном компиляторе может занимать в памяти 16 бит, в другом — 32 бита, в третьем — 8 бит. Все определяет конкретный компилятор. Правда, все стремятся к универсализации, и в основном в большинстве компиляторов тип int , например, занимает 2 байта, а тип char — один.
Я в последнее время немного затупил, не мог вспомнить, сколько байт занимает тип double в AVR-GCC . Обычно при программировании контроллеров работаешь с целочисленными типами, типа int и char , а к типам с плавающей точкой прибегаешь не часто, в связи с их ресурсоемкостью.
Поэтому, на будущее, оставлю себе здесь памятку с указанием размеров занимаемой памяти типами данных для компилятора AVR-GCC и диапазон изменения переменных этого типа.
Типы данных в языке Си для компилятора AVR-GCC
Тип | Размер в байтах (битах) |
Интервал изменения |
---|---|---|
char | 1 (8) | -128 .. 127 |
unsigned char | 1 (8) | 0 .. 255 |
signed char | 1 (8) | -128 .. 127 |
int | 2 (16) | -32768 .. 32767 |
unsigned int | 2 (16) | 0 .. 65535 |
signed int | 2 (16) | -32768 .. 32767 |
short int | 2 (16) | -32768 .. 32767 |
unsigned short int | 2 (16) | 0 .. 65535 |
signed short int | 2 (16) | -32768 .. 32767 |
long int | 4 (32) | -2147483648 .. 2147483647 |
unsigned long int | 4 (32) | 0 .. 4294967295 |
signed long int | 4 (32) | -2147483648 .. 2147483647 |
float | 4 (32) | 3.4Е-38 .. 3.4Е+38 |
double | 4 (32) | 3.4Е-38 .. 3.4Е+38 |
long double | 10 (80) | 3.4Е-4932 .. 3.4Е+4932 |
Обратите внимание
Реализация типа double в AVR-GCC отступает от стандарта. По стандарту double занимает 64 бита. В AVR-GCC переменная этого типа занимает 32 бита, и соответственно, она эквивалентна переменной с типом float !
В дополнение к этому, в библиотеках AVR-GCC введено несколько производных от стандартных типов. Они описаны в файле stdint.h . Сделано это, наверно, для улучшения наглядности и уменьшения текста программ (ускорения их написания:)). Вот табличка соответствия:
Производные типы от стандартных в языке Си для компилятора AVR-GCC
Производный тип | Стандартный тип |
---|---|
int8_t | signed char |
uint8_t | unsigned char |
int16_t | signed int |
uint16_t | unsigned int |
int32_t | signed long int |
uint32_t | unsigned long int |
int64_t | signed long long int |
uint64_t | unsigned long long int |
Тип Void
В языке Си есть еще один тип — тип void . Void используется для указания, что функция не возвращает ничего в качестве результата, или не принимает на вход никаких параметров. Этот тип не применяется для объявления переменных, соответственно он не занимает места в памяти.
В языке Си различают понятия “тип данных” и “модификатор типа”. Тип данных – это целый, а модификатор – со знаком или без знака. Целое со знаком будет иметь как положительные, так и отрицательные значения, а целое без знака – только положительные значения. В языке Си можно выделить пять базовых типов.
- char – символьный.
- int – целый.
- float – вещественный.
- double – вещественный двойной точности;
- void – не имеющий значения.
Переменная типа char имеет размер 1 байт, ее значениями являются различные символы из кодовой таблицы, например: ‘ф’, ‘:’, ‘j’ (при записи в программе они заключаются в одинарные кавычки).
Размер переменной типа int в стандарте языка Си не определен. В большинстве систем программирования размер переменной типа int соответствует размеру целого машинного слова. Например, в компиляторах для 16-разрядных процессоров переменная типа int имеет размер 2 байта. В этом случае знаковые значения этой переменной могут лежать в диапазоне от -32768 до 32767.
Ключевое слово float позволяет определить переменные вещественного типа. Их значения имеют дробную часть, отделяемую точкой, например: -5.6, 31.28 и т.п. Вещественные числа могут быть записаны также в форме с плавающей точкой, например: -1.09e+4. Число перед символом “е” называется мантиссой, а после “е” – порядком. Переменная типа float занимает в памяти 32 бита. Она может принимать значения в диапазоне от 3.4е-38 до 3.4e+38.
Ключевое слово double позволяет определить вещественную переменную двойной точности. Она занимает в памяти в два раза больше места, чем переменная типа float. Переменная типа double может принимать значения в диапазоне от 1.7e-308 до 1.7e+308.
Ключевое слово void используется для нейтрализации значения объекта, например, для объявления функции, не возвращающей никаких значений.
Типы переменных:
Программы оперируют с различными данными, которые могут быть простыми и структурированными. Простые данные – это целые и вещественные числа, символы и указатели (адреса объектов в памяти). Целые числа не имеют, а вещественные имеют дробную часть. Структурированные данные – это массивы и структуры; они будут рассмотрены ниже.
Переменная – это ячейка в памяти компьютера, которая имеет имя и хранит некоторое значение. Значение переменной может меняться во время выполнения программы. При записи в ячейку нового значения старое стирается.
Хорошим стилем является осмысленное именование переменных. Имя переменной может содержать от одного до 32 символов. Разрешается использовать строчные и прописные буквы, цифры и символ подчёркивания, который в Си считается буквой. Первым символом обязательно должна быть буква. Имя переменной не может совпадать с зарезервированными словами.
Тип char
char – является самым экономным типом. Тип char может быть знаковым и беззнаковым. Обозначается, как “signed char” (знаковый тип) и “unsigned char” (беззнаковый тип). Знаковый тип может хранить значения в диапазоне от -128 до +127. Беззнаковый – от 0 до 255. Под переменную типа char отводится 1 байт памяти (8 бит).
Ключевые слова signed и unsigned указывают, как интерпретируется нулевой бит объявляемой переменной, т.е., если указано ключевое слово unsigned, то нулевой бит интерпретируется как часть числа, в противном случае нулевой бит интерпретируется как знаковый.
Тип int
Целочисленная величина int может быть short (короткой) или long (длинной). Ключевое слово short ставится после ключевых слов signed или unsigned. Таким образом, есть типы: signed short int, unsigned short int, signed long int, unsigned long int.
Переменная типа signed short int (знаковая короткая целая) может принимать значения от -32768 до +32767, unsigned short int (беззнаковая короткая целая) – от 0 до 65535. Под каждую из них отводится ровно по два байта памяти (16 бит).
При объявлении переменной типа signed short int ключевые слова signed и short могут быть пропущены, и такой тип переменной может быть объявлен просто int. Допускается и объявление этого типа одним ключевым словом short.
Переменная unsigned short int может быть объявлена как unsigned int или unsigned short.
Под каждую величину signed long int или unsigned long int отводится 4 байта памяти (32 бита). Значения переменных этого типа могут находиться в интервалах от -2147483648 до 2147483647 и от 0 до 4294967295 соответственно.
Существуют также переменные типа long long int, для которых отводится 8 байт памяти (64 бита). Они могут быть знаковыми и беззнаковыми. Для знакового типа диапазон значений лежит в пределах от -9223372036854775808 до 9223372036854775807, для беззнакового – от 0 до 18446744073709551615. Знаковый тип может быть объявлен и просто двумя ключевыми словами long long.
Тип | Диапазон | Шестнадцатеричный диапазон | Размер |
unsigned char | 0 … 255 | 0x00 … 0xFF | 8 bit |
signed char
или просто char |
-128 … 127 | -0x80 … 0x7F | 8 bit |
unsigned short int
или просто unsigned int или unsigned short |
0 … 65535 | 0x0000 … 0xFFFF | 16 bit |
signed short int
или signed int
или просто short или int |
-32768 … 32767 | 0x8000 … 0x7FFF | 16 bit |
unsigned long int
или просто unsigned long |
0 … 4294967295 | 0x00000000 … 0xFFFFFFFF | 32 bit |
signed long
или просто long |
-2147483648 … 2147483647 | 0x80000000 … 0x7FFFFFFF | 32 bit |
unsigned long long | 0 … 18446744073709551615 | 0x0000000000000000 … 0xFFFFFFFFFFFFFFFF | 64 bit |
signed long long
или просто long long |
-9223372036854775808 … 9223372036854775807 | 0x8000000000000000 … 0x7FFFFFFFFFFFFFFF | 64 bit |
Объявление переменных
Переменные объявляют в операторе описания. Оператор описания состоит из спецификации типа и списка имён переменных, разделённых запятой. В конце обязательно должна стоять точка с запятой.
[модификаторы] спецификатор_типа идентификатор [, идентификатор] ...
Модификаторы – ключевые слова signed, unsigned, short, long.
Спецификатор типа – ключевое слово char или int, определяющее тип объявляемой переменной.
Идентификатор – имя переменной.
Char x; int a, b, c; unsigned long long y;
При объявлении переменную можно проинициализировать, то есть присвоить ей начальное значение.
Int x = 100;
В переменную x при объявлении сразу же будет записано число 100. Инициализируемые переменные лучше объявлять в отдельных строках.