Что определяет тип данных переменной
Структура языка программирования
Содержание
Дополнительно
Классификация типов данных
Для простых типов данных определяются границы диапазона и количество байт, занимаемых ими в памяти компьютера.
В большинстве языков программирования, простые типы жестко связаны с их представлением в памяти компьютера. Компьютер хранит данные в виде последовательности битов, каждый из которых может иметь значение 0 и 1. Фрагмент данных в памяти может выглядеть следующим образом
Данные на битовом уровне (в памяти) не имеют ни структуры, ни смысла. Как интерпретировать данные, как целочисленное число, или вещественное, или символ, зависит от того, какой тип имеют данные, представленные в этой и последующих ячейках памяти.
Числовые типы данных
Целочисленные типы данных
Исходя из машинного представления целого числа, в ячейке памяти из n бит может хранится 2 n для беззнаковых, и 2 n-1 для знаковых типов.
Рассмотрим теперь конкретные целочисленные типы в трёх языках.
У некоторых типов есть приписка «16 разрядов» или «32 разряда». Это означает, что в зависимости от разрядности операционной системы и компилятора данный тип будет находится в соответствующем диапазоне. По-этому, рекомендуется не использовать int, unsigned int, а использовать их аналоги, но уже жестко определенные, short, long, unsigned short, unsigned long.
В Java нет беззнаковых целочисленных типов данных.
Вещественные типы данных
Числа вещественного типа данных задаются в форме чисел с плавающей запятой.
Плавающая запятая — форма представления действительных чисел, в которой число хранится в форме мантиссы и показателя степени. В случае языков программирования, любое число может быть представлено в следующем виде
Вывод: вещественные типы данных, в отличии от целочисленных, характеризуются диапазоном точности и количеством значащих разрядов.
Рассмотрим конкретные типы данных в наших трёх языках.
Тип decimal создан специально для операций высокой точности, в частности финансовых операций. Он не реализован как примитивный тип, по-этому его частое использование может повлиять на производительность вычислений.
Символьный тип данных
Значение переменной этого типа данных представляет собой один символ. В действительности, это есть целое число. В зависимости от кодировки, это число превращается в некий символ. Данные типы данных характеризуются лишь размером выделяемой под них памяти.
Логический тип данных
Перечислимый тип данных
Во внутреннем представлении, это целочисленный тип данных, только здесь пользователь вместо числе использует заранее определенные строковые значения.
Чтобы прочувствовать эту концепцию, приведем пример на языке С++ (в С# и Java аналогично)
Теперь переменные перечислимого типа Forms могут принимать лишь значения, определенные в примере кода. Это очень удобно, ведь мы уже оперируем не с числами, а с некими смысловыми значениями, замечу лишь, что для компьютера эти значения всё-равно являются целыми числами.
Массив
Каждый массив характеризуется типом данных его элементов, который может быть как простым, так и сложным, то есть любым.
В языках программирования нельзя оперировать всем массивом, работают с конкретным элементом. Чтобы доступиться до него в трёх рассматриваемых нами языках используют оператор «[]».
Структура
Структуры реализованы в языке программирования, чтобы собрать некие близки по смыслу вещи воедино.
Например, есть колесо автомобиля. У колеса есть диаметр, толщина, шина. Шина в свою очередь является структурой, у которой есть свои параметры: материал, марка, чем заполнена. Естественно, для каждого параметра можно создать свою переменную или константу, у нас появится большое количество переменных, которые, чтобы понять к чему они относятся, нужно в именах общую часть выделять. Имена будут нести лишнюю смысловую нагрузку. Получается запутанная история. А так мы определяем две структуры, а затем параметры в них.
Класс
Еще одним пользовательским типом данных является класс. Класс умеет всё, что и структура, но кроме параметров, у него есть и методы, и поддерживает большое количество вещей, связанных с объектно-ориентированным программированием.
Система типов C++
Терминология
Переменная: символическое имя количества данных, чтобы имя можно было использовать для доступа к данным, на которые он ссылается в области кода, где он определен. В C++ переменная обычно используется для ссылки на экземпляры скалярных типов данных, тогда как экземпляры других типов обычно называются объектами.
Объект. для простоты и согласованности в этой статье используется объект term для ссылки на любой экземпляр класса или структуры, и когда он используется в общем смысле, включает все типы, даже скалярные переменные.
Тип POD (обычные старые данные): Эта неофициальная Категория типов данных в C++ относится к скалярным типам (см. раздел фундаментальные типы) или к классам Pod. Класс POD не содержит статических данных-членов, которые не являются типами POD, а также не содержит пользовательских конструкторов, пользовательских деструкторов или пользовательских операторов присваивания. Кроме того, класс POD не имеет виртуальных функций, базового класса и ни закрытых, ни защищенных нестатических данных-членов. Типы POD часто используются для внешнего обмена данными, например с модулем, написанным на языке С (в котором имеются только типы POD).
Указание типов переменных и функций
C++ — это строго типизированный язык, который также является статически типизированным; Каждый объект имеет тип, и этот тип никогда не изменяется (не следует путать с статическими объектами данных). При объявлении переменной в коде необходимо либо явно указать ее тип, либо использовать auto ключевое слово, чтобы указать компилятору вывести тип из инициализатора. При объявлении функции в коде необходимо указать тип каждого аргумента и его возвращаемое значение или void значение, если функция не возвращает никакого значения. Исключением является использование шаблонов функции, которые допускают аргументы произвольных типов.
После объявления переменной изменить ее тип впоследствии уже невозможно. Однако можно скопировать значения переменной или возвращаемое значение функции в другую переменную другого типа. Такие операции называются преобразованиями типов, которые иногда являются обязательными, но также являются потенциальными источниками потери или неправильности данных.
При объявлении переменной типа POD настоятельно рекомендуется инициализировать ее, т. е. указать начальное значение. Пока переменная не инициализирована, она имеет «мусорное» значение, определяемое значениями битов, которые ранее были установлены в этом месте памяти. Необходимо учитывать эту особенность языка C++, особенно при переходе с другого языка, который обрабатывает инициализацию автоматически. При объявлении переменной типа, не являющегося классом POD, инициализация обрабатывается конструктором.
В следующем примере показано несколько простых объявлений переменных с небольшим описанием для каждого объявления. В примере также показано, как компилятор использует сведения о типе, чтобы разрешить или запретить некоторые последующие операции с переменной.
Базовые (встроенные) типы
Базовые типы распознаются компилятором, в котором предусмотрены встроенные правила, управляющие операциями, выполняемыми с такими типами, а также преобразованием в другие базовые типы. Полный список встроенных типов, а также их размер и числовые ограничения см. в разделе Встроенные типы.
На следующем рисунке показаны относительные размеры встроенных типов в реализации Microsoft C++:
В следующей таблице перечислены наиболее часто используемые фундаментальные типы и их размеры в реализации Microsoft C++:
Другие реализации C++ могут использовать разные размеры для определенных числовых типов. Дополнительные сведения о размерах и отношениях размеров, необходимых стандарту C++, см. в разделе Встроенные типы.
Тип void
Квалификатор типа const
Любой встроенный или пользовательский тип может квалифицироваться ключевым словом const. Кроме того, функции-члены могут быть const полными и даже const перегруженными. Значение const типа не может быть изменено после инициализации.
Строковые типы
Определяемые пользователем типы
Компилятор не имеет встроенных сведений о пользовательском типе. Он узнает о типе при первом обнаружении определения во время процесса компиляции.
типы указателей
Как и самые ранние версии языка C, язык C++ по-прежнему позволяет объявить переменную типа указателя с помощью специального декларатора * (звездочка). Тип указателя хранит адрес расположения в памяти, в котором хранится фактическое значение данных. В современных C++ они называются необработанными указателямии доступны в коде с помощью специальных операторов (звездочки) или -> (тире с символом «больше»). Это называется разыменованием, и какой из используемых объектов зависит от того, выполняется ли разыменование указателя на скаляр или указатель на член в объекте. Работа с типами указателя долгое время была одним из наиболее трудных и непонятных аспектов разработки программ на языках C и C++. В этом разделе приводятся некоторые факты и рекомендации по использованию необработанных указателей, если вы хотите, но в современной версии C++ больше не требуется (или рекомендуется) использовать необработанные указатели для владения объектами, так как при развитии интеллектуального указателя (см. Дополнительные сведения в конце этого раздела). Все еще полезно и безопасно использовать необработанные указатели для отслеживания объектов, но если требуется использовать их для владения объектом, необходимо делать это с осторожностью и после тщательного анализа процедуры создания и уничтожения объектов, которые им принадлежат.
Первое, что необходимо знать, — это то, что при объявлении переменной необработанного указателя выделяется только память, необходимая для хранения адреса расположения памяти, на который будет ссылаться указатель при разыменовывании. Выделение памяти для самого значения данных (также называемое резервным хранилищем) еще не выделено. Другими словами, объявив переменную необработанного указателя, вы создаете переменную адреса памяти, а не фактическую переменную данных. Разыменовывание переменной указателя до проверки того, что она содержит действительный адрес в резервном хранилище, приведет к неопределенному поведению (обычно неустранимой ошибке) программы. В следующем примере демонстрируется подобная ошибка:
Пример разыменовывает тип указателя без выделения памяти для хранения фактических целочисленных данных или без выделенного допустимого адреса памяти. В следующем коде исправлены эти ошибки:
Однако можно легко забыть удалить динамически выделенный объект, особенно в сложном коде, который вызывает ошибку ресурса, называемую утечкой памяти. По этой причине в современном С++ настоятельно не рекомендуется использовать необработанные указатели. Почти всегда лучше обернуть необработанный указатель в Интеллектуальный указатель, который автоматически освобождает память при вызове его деструктора (когда код выходит за пределы области для смарт-указателя); с помощью смарт-указателей вы практически устраняете целый класс ошибок в программах на C++. В следующем примере предположим, что MyClass — это пользовательский тип, который имеет открытый метод DoSomeWork();
Дополнительные сведения о смарт-указателях см. в разделе интеллектуальные указатели.
Дополнительные сведения о преобразовании указателей см. в разделе преобразования типов и типизация.
Дополнительные сведения об указателях в целом см. в разделе указатели.
Типы данных Windows
Дополнительные сведения
Дополнительные сведения о системе типов C++ см. в следующих разделах.
Преобразования типов и безопасность типов
Описание типовых проблем преобразования типов и способов их избежать.
Сводка типов данных
Тип данных — это характеристика переменной, определяющая тип содержащихся в ней данных. К типам данных относятся типы, указанные в таблице ниже, а также пользовательские типы и определенные типы объектов.
Набор встроенных типов данных
В следующей таблице показываются поддерживаемые типы данных, включая размеры хранилищ и диапазоны.
| Тип данных | Размер хранилища | Диапазон |
|---|---|---|
| Boolean | 2 байта | True или False |
| Byte | 1 байт | от 0 до 255 |
| Collection | Неизвестно | Неизвестно |
| Currency (масштабируемое целое число) | 8 байт | от –922 337 203 685 477,5808 до 922 337 203 685 477,5807 |
| Date | 8 байт | от 1 января 100 г. до 31 декабря 9999 г. |
| Decimal | 14 байт | +/–79 228 162 514 264 337 593 543 950 335 без десятичной запятой +/–7,9228162514264337593543950335 с 28 разрядами справа от десятичной запятой Наименьшее ненулевое число равно +/–0,0000000000000000000000000001 |
| Dictionary | Неизвестно | Неизвестно |
| Double (число с плавающей запятой двойной точности) | 8 байт | от –1,79769313486231E308 до –4,94065645841247E-324 для отрицательных значений от 4,94065645841247E-324 до 1,79769313486232E308 для положительных значений |
| Integer | 2 байта | от –32 768 до 32 767 |
| Long (целое число Long) | 4 байта | от –2 147 483 648 до 2 147 483 647 |
| LongLong (целое число LongLong) | 8 байт | от –9 223 372 036 854 775 808 до 9 223 372 036 854 775 807 Действительно только для 64-разрядных платформ. |
| LongPtr (целое число Long в 32-разрядных системах, целое число LongLong в 64-разрядных системах) | 4 байта в 32-разрядных системах 8 байт в 64-разрядных системах | от –2 147 483 648 до 2 147 483 647 в 32-разрядных системах от –9 223 372 036 854 775 808 до 9 223 372 036 854 775 807 в 64-разрядных системах |
| Object | 4 байта | Любая ссылка на Object |
| Single (число с плавающей запятой одинарной точности) | 4 байта | от –3,402823E38 до –1,401298E-45 для отрицательных значений от 1,401298E-45 до 3,402823E38 для положительных значений |
| String (переменная длина) | 10 байтов + длина строки | от 0 до приблизительно 2 миллиардов |
| String (фиксированная длина) | Длина строки | от 1 до приблизительно 65 400 |
| Variant (с числами) | 16 байт | Любое числовое значение до диапазона типа Double |
| Variant (с символами) | 22 байта + длина строки (24 байтов в 64-разрядных системах) | Тот же диапазон как для типа String переменной длины |
| Определяется пользователем (используя Type) | Число, необходимое для элементов | Диапазон каждого элемента совпадает с диапазоном его типа данных. |
Тип Variant, содержащий массив, требует на 12 байт больше, чем сам массив.
Для массивов данных любого типа требуются 20 байтов памяти плюс 4 байта на каждую размерность массива, плюс количество байтов, занимаемых самими данными. Память, занимаемая данными, может быть вычислена путем умножения количества элементов данных на размер каждого элемента.
Например, данные в одномерном массиве, состоящем из 4 элементов данных Integer размером 2 байта каждый занимают 8 байтов. 8 байтов, необходимых для данных, плюс 24 байта служебных данных составляют 32 байта полной памяти, требуемой для массива. На 64-разрядных платформах массив SAFEARRAY занимает 24 бита (плюс 4 байта на оператор Dim). Элемент pvData является 8-байтным указателем, и он должен находиться в границах 8 байтов.
Тип LongPtr не является настоящим типом данных, так как он преобразуется в тип Long в 32-разрядных средах или в тип LongLong в 64-разрядных средах. Тип LongPtr должен использоваться для представления указателя и обработки значений в операторах Declare и позволяет писать переносимый код, который может выполняться как в 32-разрядных, так и в 64-разрядных средах.
Для преобразования одного типа строковых данных в другой используется функция StrConv.
Преобразование между типами данных
В статье Функции преобразования типов приведены примеры использования следующих функций для приведения выражения к определенному типу данных: CBool, CByte, CCur, CDate, CDbl, CDec, CInt, CLng, CLngLng, CLngPtr, CSng, CStr и CVar.
Ниже приведены страницы соответствующих функций: CVErr, Fix и Int.
Функция CLngLng действительна только для 64-разрядных платформ.
Проверка типов данных
Чтобы проверить типы данных, ознакомьтесь с приведенными ниже функциями.
Возвращаемые значения функции CStr
| Если expression | CStr возвращает |
|---|---|
| Boolean | Строка, содержащая значение True или False. |
| Date | Строка, содержащая полный или краткий формат даты, установленный в системе. |
| Empty | Строка нулевой длины («»). |
| Error | Строка, содержащая слово Error и номер ошибки. |
| Null | Ошибка во время выполнения. |
| Другое числовое значение | Строка, содержащая число |
См. также
Поддержка и обратная связь
Есть вопросы или отзывы, касающиеся Office VBA или этой статьи? Руководство по другим способам получения поддержки и отправки отзывов см. в статье Поддержка Office VBA и обратная связь.
Что определяет тип данных переменной
Контекстное определение типа данных в Си
Вся мебель в ней дубовая.
Идея контекстного определения типа данных состоит в том, что определяемая переменная помещается в контекст (окружение) тех операций, с которыми она может быть использована. В более широком плане это восходит к способу определения предметов через действия, которые над ними можно произвести, т.е. «автомобиль – это то, на чем ездят». Поскольку речь идет об определении переменных производного типа данных, то операции, которые применимы к нему – это не арифметические и им подобные, а операции выделения составляющего типа данных. Если при классификации операций исходить из их функционального назначения, то для переменной каждого производного типа данных можно выделить операцию, при помощи которой можно добраться до составляющих ее компонент.
Использование в контекстном определении
Таким образом, если в контексте (окружении) переменной встречается такая операция, то можно догадаться, к какому производному типу данных относится сама переменная. Поэтому контекстное определение переменной использует эти операции следующим образом :
· определение переменной содержит имя переменной в окружении (контексте) операций выделения составляющего типа данных, последовательно выполняемых над ней;
· операции записываются в той последовательности, в которой они могут быть применены к переменной, с учетом их естественных приоритетов. Для изменения естественной последовательности могут использоваться приоритетные скобки ;
· в результате последовательного применения указанных операций получается тип данных, стоящий слева в определении.
Контекстное определение типа понимается следующим образом. Если взять переменную некоторого неизвестного пока типа данных и выполнить над ней последовательность операций выделения составляющих типов данных, то в результате получится переменная того типа данных, который указан в левой части определения. При этом должны соблюдаться приоритеты выполнения операций, а для их изменения использоваться круглые скобки. Полученная последовательность выполнения операций дает обратную последовательность определений типов от базового к производному, начиная с типа, стоящего слева. Рассмотрим несколько примеров.
Естественно, что не все сочетания типов данных допустимы, а только те, которые напрямую представимы в компьютерной архитектуре (что следует из свойств самого Си). Например, массив указателей (адресов) функций допустим, а массив функций – нет, поскольку адреса (указатели) имеют фиксированную размерность и допускают копирование, а тип данных – функция допускает только вызов.
void ( pp [10])(); // Массив функций – что это такое.
Синтаксис контекстного определения не ограничивается обычными переменными. Он появляется всегда, когда речь заходит о типизированных компонентах программы. По правилам контекстного определения записываются :
· определения и описания переменных;
· формальные параметры функций;
· определения элементов структуры ( struct);
· определения абстрактных типов данных;
· определения промежуточных типов данных (спецификатор typedef).
Иерархия типов данных и переменных
Любая программа задает иерархическую систему типов данных, на основе которой определяются переменные. Наконец-то мы может соединить воедино все средства, предназначенные в Си для этих целей. Прежде всего, программа оперирует набором имен, которые обозначают типы данных, «источники» их появления в программе могут быть самыми разными:
· имена базовых типов данных заданы в трансляторе «от рождения»;
Кроме этих явно заданных имен в иерархии типов возможны неявно заданные промежуточные типы, которые вводятся вышеупомянутыми контекстными определениями. Если же тип данных упоминается сам по себе, безотносительно к какой-либо переменной, то это можно сделать с использованием абстрактного типа данных.
· в операторе создания динамических переменных new;
· в операции явного преобразования типа данных;
· при объявлении формальных параметров внешней функции с использованием прототипа.
char name[20]; // Элементы структуры
Это определение создает систему явно поименованных и промежуточных типов, порождающих переменные.

рис.55.1. Иерархия типов данных и переменных
Функция как тип данных
Указатель на массив
Поскольку любой указатель может ссылаться на массив, термин «указатель на массив» для Си – то же самое, что «масло масляное». Тем не менее, он имеет смысл, если речь идет об указателе на область памяти, содержащей двумерный массив (матрицу), а адресуемой единицей является одномерный массив (строка).
for (int j=0; (*p)[j]; j++) putchar((*p)[j]);
Вопросы без ответов
Определите вид объекта (переменная, функция), задаваемого в контекстном определении или объявлении, а также все неявно заданные типы данных. Найдите абстрактный тип данных и определите назначение.

