В C и C#, как и в ряде других языков программирования, типы данных имеют особое значение. Не во всех ЯП типизация одинаково важна – существуют языки, в которых она может не указываться. В таких случаях система все определит самостоятельно. C и C# относятся к языкам со строгой типизацией, поэтому здесь придется указывать, с какой именно переменной предстоит иметь дело.
Строгая типизация указывает на то, что все операции будут подвергаться строгому контролю со стороны компилятора на соответствие типов. Недопустимые команды и манипуляции в процессе запуска созданного программного обеспечения компилироваться не будут.
Такой контроль дает возможность исключить ошибки в работе исходного приложения, а также повысить надежность программ. Для того, чтобы контролировать типы всех переменных, значения и выражения должны принадлежать к определенному виду. Понятия переменного «бестипового» характера в этих языках нет.
Далее предстоит изучить основные типы переменных в C и C#. Эта информация пригодится как новичкам, так и тем, кто уже немного разбирается в программировании. Она поможет понять, какие «виды» переменных можно использовать в упомянутых языках, а также какие особенности имеет каждый из них.
Система типов – это…
Система типов Си – это реализация понятия типа данных в языке Си. Этот язык предоставляет базовые арифметические «виды» и синтаксис для создания массивов и составных типов. Некоторые заголовочные файлы из стандартной библиотеки C предусматривают определения типов с дополнительными параметрами.
Тип значения определит те операции в C# и C, которые можно выполнять над ними, а также объяснит системе (компилятору), как обрабатывать те или иные переменные/значения. Операции, которые разрешены для одного типа данных, могут оказаться под запретом для других.
В C# поддерживаются две общие категории встроенных типов данных:
- типы значений;
- ссылочные типы.
Они будут отличаться по содержимому заданной переменной. Разница между ними заключается в том, что value type (тип значения) хранит данные непосредственно, а reference type (ссылочный тип) хранит ссылку на значение.
Соответствующие типы будут сохраняться в разных местах памяти: типы значений – в стеке, а ссылочные – в управляемой куче.
Базовые типы в C
В C много базовых типов. Большинство из них состоит из одного-четырех спецификаторов типа (float, char, int, double) и опциональных спецификаторов (short, long, signed, unsigned). На подавляющем большинстве современных платформ 1 байт = 8 бит, но бывают исключительные ситуации, при которых 1 байт = 16 бит или другому числу. Обычно им выступает степень двойки.
Тип | Описание | Спецификатор |
Char | Целочисленный тип. Самый маленький из всех возможных. Может включать в себя базовый символьный набор. Бывает знаковым и беззнаковым – в зависимости от реализации. | %c |
Signed char | Имеет тот же размер, что и char, но гарантированно имеет знак. Способен принимать значения как минимум из диапазона [-127, +127]. Обычно встречается в реализациях [-128, +127] | %c. Можно также воспользоваться записями: %d, %hhi, %hhx, %hho для вывода в числовом формате. |
Unsigned char | Того же размера, что и char, но без знака. Диапазон значений – [0, 255)/ | %с (или %hhu для вывода в числовой форме). |
Short, short int, signed short, signed short short int | Тип короткого целочисленного значения со знаком. Может включать в себя числа [-32767, +32767]. | %hi |
Unsigned short и unsigned short int | То же самое, что и short, но без знака. Диапазон значений – [0, +65535] | %hu |
Int, signed, signed int | Ключевой тип целого числа, имеющего знак. Может включать в себя числа диапазона [-32767, +32767]. Имеет размер минимум 2 байта (или 16 бит). В современных компиляторах для 32- и более разрядных платформ имеет размер 4 байта и диапазон [-2 147 483 648, +2 147 483 647]. На платформах 16 и 8 бит имеет размер 2 байта. | %i или %d |
Unsigned, unsigned int | То же самое, что и int, но без знака. Диапазон – [0, +4 294 967 295). | %u |
Long, long int, signed long, signed long int | Тип длинного целочисленного значения со знаком. Может включать в себя числа из диапазона [-2 147 483 647, +2 147 483 647]. «Весит» минимум 32 бита (или 4 байта). | %li |
Unsigned long, unsigned long int | То же самое, что и long, но без знака. Диапазон – [0, +4 294 967 295]. | %lu |
Long long, long long int, signed long long, signed long long int | Тип длинного целого числа со знаком. Может называться двойное длинное. Включает в себя числа из диапазона [-9 223 372 036 854 775 808, +9 223 372 036 854 775 807. Это – 64 бита. | %lli, %lld |
Unsigned long long, unsigned long long int | Напоминает long long, но беззнаковый. Диапазон значений – [0, 18 446 744 073 709 551 615]. | %llu |
Float | Тип вещественного числа с плавающей запятой. Обычно называется типом числа одинарной точности с плавающей запятой. | %f (автоматически происходит преобразование в double для printf. |
Double | Тип вещественного числа с плавающей запятой. Это тип числа двойной точности с плавающей запятой. | %f, %lf, %g, %e |
Long double | Тип вещественного числа с плавающей запятой повышенной точности. Может выступать 80-битным форматом с плавающей запятой. | %LF %LF, %LG %LG, %Le %LE |
Теперь понятно, какие базовые типы встречаются в C у чисел. Есть еще один вариант, который очень важен для разработчиков и основной массы современных приложений.
Логический тип
В C99 был добавлен еще один тип. Он называется логическим (_Bool). Дополнительный заголовочный файл <stdbool.h> определит для него псевдоним bool, а также макросы true (истина) и false (ложь).
_Bool ведет себя точно также, как и обычный встроенный тип, но с одним исключением: любое ненулевое (не ложное) присваивание будет сохранено в качестве единицы. Это помогает избегать переполнения.
Типы значений в C#
Основные «виды» переменных в C понятны. Теперь можно рассмотреть их на примере C#. Для этого языка предстоит разобрать типизацию более подробно.
Целочисленные
В C# поддерживаются девять целочисленных значений:
- byte;
- sbyte;
- char;
- long;
- ulong;
- short;
- ushort;
- uuint;
- int.
Char будет применяться для представления символов, поэтому он обычно рассматривается отдельно. Остальные восемь целочисленных используются для числовых расчетов. Int в C# выступает самым используемым.
Ниже можно увидеть диапазоны их значений, а также разрядность в битах:
Отрицательные двоичные числа практически всегда представляются методом дополнения до двух. Согласно этому правилу, все двоичные разряды отрицательного числа сначала инвертируются, а затем к соответствующему числу прибавляется 1.
Int – наиболее распространенный тип. Он используется для управления массивами, циклами, а также для математических расчетов общего назначения. Если значение требуется сохранить без знака, необходимо выбрать uint. Для больших значений – со знаком long, без него – ulong.
С плавающей точкой
С их помощью можно представлять числа с дробными частями. Можно выделить double и float в C Sharp в соответствующей категории значений. Они представляют числа с двойной и одинарной точностью соответственно.
У float разрядность составляет 32 бита, у double – 64. Float используется для меньших значений с плавающей точкой, для которых необходима меньшая точность. Пользоваться double рекомендуется, когда нужна высокая степень точности (15 разрядов).
Если нецелочисленное значение жестко кодируется в исходном тексте, обычно компилятор предполагает, что планируется использование double. Когда значение требуется специфицировать в качестве float, к нему необходимо добавить символ f (или F).
Выше – наглядный пример того, как это будет выглядеть в реализации в программном коде.
Десятичные
Для того, чтобы представить числа с высокой точностью, существует десятичный тип – decimal. Он используется при финансовых расчетах. Обладает разрядностью 128 бит.
Decimal позволяет представлять числа с точностью до 28 десятичных разрядов. За счет этого десятичные значения используются в программном обеспечении без ошибок округления. Тип особо полезен и удобен для расчетов, которые связаны с финансами.
Символы
C# имеет отдельное «обозначение» для символов. Они представлены в этом языке программирования не 8-разрядным кодом, как в C++, а 16-разрядным – в Юникоде. В нем символьный набор настолько широк, что он охватывает символы практически из всех естественных языков на свете.
Чтобы представить иероглифы и некоторые мировые алфавиты, определен тип char, который представляет 16-разрядные значения без знака. Диапазон принимаемых значений составляет от 0 до 65 535. Стандартный символьный набор в 8-разрядном коде ASCII – это подмножество Юникода в пределах от 0 до 127. Это указывает на то, что в Unicode представлены и остаются действительными все ASCII.
Чтобы присвоить значение символьной переменной, это значение необходимо заключить в одинарные кавычки:
Выше – пример того, как соответствующий процесс будет выглядеть в программном коде. Несмотря на то, что char определен в C# как целочисленный, его не рекомендуется путать с остальными целочисленными. Связано это с тем, что в C# отсутствует автоматическое преобразование символьных значений в целочисленные и обратно.
Наравне представления char как символьных литералов, их можно представить в качестве 4-разрядных шестнадцатеричных значений Юникода (пример – \u0041), целочисленных значений с приведением или шестнадцатеричных значений. Они также могут быть представлены управляющей последовательностью.
Логические данные
Bool предоставляет возможность использования двух логических значений:
- истина (true);
- ложь (false).
Переменная или выражения bool будут принимать одно из представленных значений. В C# не определено взаимное преобразование логических и целых значений. Пример – 1 не может быть преобразована в true, а 0 – в значение false.
Литералы
Литералы – это фиксированные значения в программе, не требующие вычислений. Они тоже присутствуют в C#. Обычно представлены как true и false, используются для инициализации переменных логического типа. Это постоянные значения, представленные в удобной для восприятия форме.
Целочисленные литералы указываются как числа без дробной части, с плавающей точкой (floating point C) – указывается точка и десятичная числовая часть. Для указания long используется суффикс l или L, беззнаковый литерал требует прибавления u или U. Float соответственно предусматривает приписку d или D, а float – f или F. Decimal обозначается как m/M.