Чем word отличается от int
Обновлено: 07.07.2024
Если вы уверенно сможете правильно ответить на эти вопросы, тогда эта статья не для вас. В противном случае десять минут, потраченные на её чтение, будут весьма полезны.
- Знаковые оба.
- Законны оба.
- 8.
- 2147483647. -2147483648.
- Конечно, Кэп.
- char — не регламентируется, int — знаковый.
- Для int — законно, а для char — нет.
- Не менее 8.
- 32767. -32767
- Вообще говоря, нет.
Про signed и unsigned
Все целочисленные типы кроме char , по умолчанию знаковые (signed).
С char ситуация сложнее. Стандарт устанавливает три различных типа: char , signed char , unsigned char . В частности, указатель типа (signed char *) не может быть неявно приведён к типу (char *) .
Хотя формально это три разных типа, но фактически char эквивалентен либо signed char , либо unsigned char — на выбор компилятора (стандарт ничего конкретного не требует).
Подробнее про char я написал в комментариях.
О размере unsigned char
Тип unsigned char является абстракцией машинного байта. Важность этого типа проявляется в том, что С может адресовать память только с точностью до байта. На большинстве архитектур размер байта равен 8 бит, но бывают и исключения. Например, процессоры с 36-битной архитектурой как правило имеют 9-битный байт, а в некоторых DSP от Texas Instruments байты состоят из 16 или 32 бит. Древние архитектуры могут иметь короткие байты из 4, 5 или 7 бит.
Размеры целочисленных типов в С
C переносимый, поэтому в нём базовые целочисленные типы ( char , short , int и др.) не имеют строго установленного размера, а зависят от платформы. Однако эти типы не были бы переносимы, если бы
их размеры были совершенно произвольные: стандарт устанавливает минимальные диапазоны принимаемых значений для всех базовых целочисленные типов. А именно,
- signed char: -127. 127 (не -128. 127; аналогично другие типы)
- unsigned char : 0. 255 (= 2 8 −1)
- signed short : -32767. 32767
- unsigned short : 0. 65535 (= 2 16 −1)
- signed int : -32767. 32767
- unsigned int : 0. 65535 (= 2 16 −1)
- signed long : -2147483647. 2147483647
- unsigned long : 0. 4294967295 (= 2 32 −1)
- signed long long : -9223372036854775807. 9223372036854775807
- unsigned long long : 0. 18446744073709551615 (= 2 64 −1)
Стандарт требует sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long) <= sizeof(long long) . Таким образом, вполне законны ситуации типа sizeof(char)=sizeof(long)=32 . Для некоторых DSP от Texas Instruments так и есть.
Конкретные значения этих диапазонов для данной платформы указаны заголовочном файле limits.h .
Новые типы в С99
После того, как C99 добавил тип long long , целочисленных типов и путаницы стало ещё больше. Чтобы навести порядок, стандарт ввёл заголовочный файл stdint.h , где определяются типы вроде int16_t (равно 16 бит), int_least16_t (минимальный тип, способный вместить 16 бит), int_fast16_t (по крайней мере 16 бит, работа с этим типом наиболее быстрая на данной платформе) и т. п.
least- и fast-типы фактически являются заменой рассмотренных выше типов int , short , long и т. п. только вдобавок дают программисту возможность выбора между скоростью и размером.
От типов вроде int16_t , со строгим указанием размера, страдает переносимость: скажем, на архитектуре с 9-битным байтом может просто не найтись 16-битного регистра. Поэтому стандарт тут явно говорит, что эти типы опциональны. Но учитывая, что какой бы код вы ни писали, чуть менее чем во всех случаях целевая архитектура фиксирована даже в худшем случае с точностью до семейства (скажем, x86 или AVR), внутри которого, размер байта не может вдруг поменяться, то переносимость фактически сохраняется. Более того, типы вроде int16_t оказались даже более популярными, чем int_least16_t и int_fast16_t , а при низкоуровневом программировании (микроконтроллеры, драйверы устройств) и подавно, ибо там зачастую неопределённость размера переменной просто непозволительна.
1) Для удобства тройку архитектура+ОС+компилятор далее будем называть просто платформой.
2) Этот макрос правильнее было бы назвать UCHAR_BIT , но по причинам совместимости он называется так, как называется.
BYTE, WORD, DWORD, SINT, USINT, INT, UINT, DINT, и UDINT -- все это целочисленные типы.
Слово (WORD) - является типом данных «цепочка из 16 бит». Значения чисел этого типа могут быть представлены в двоичной, восьмеричной или шестнадцатеричной системах счисления. Длинна элементов данных этого типа данных 16 бит. Этот тип не может принимать числовое значение.
Двойное слово DWORD - 32-битное беззнаковое целое.
Тип INT является типом данных «целое число». Значения чисел этого типа могут быть представлены в двоичной, восьмеричной или шестнадцатеричной системах счисления. Длина элемента данных 16 бит. Диапазон значений для переменных данных этого типа от -215 до 215-1.
Тип DINT является типом данных «целое число двойной длинны». Значения чисел этого типа могут быть представлены в двоичной, восьмеричной или шестнадцатеричной системах счисления. Длина элемента данных 32 бит. Диапазон значений для переменных этого типа данных от -231 до 231-1.
Тип UDINT является типом данных «целое число двойной длинны без знака». Значения чисел этого типа могут быть представлены в двоичной, восьмеричной или шестнадцатеричной системах счисления. Длина элемента данных 32 бит. Диапазон значений для переменных данных этого типа от 0 до 232-1.
Тип UINT является типом данных «целое число без знака». Значения чисел этого типа могут быть представлены в двоичной, восьмеричной или шестнадцатеричной системах счисления. Длина элемента данных 16 бит. Диапазон значений для переменных данных этого типа от 0 до 216-1.
Тип BYTE является типом данных «цепочка из 8 бит». Цепочки данного типа могут быть представлены в двоичной, восьмеричной или шестнадцатеричной системах счисления. Длинна элементов этого типа данных 8 бит. Этому типу данных не может быть присвоено числовое значение.
Они отличаются различным диапазоном сохраняемых данных и, естественно, различными требованиями к памяти. Подробно данные характеристики представлены в следующей таблице:
▌ Немного истории
Надеюсь, что статья и доводы в ней подтвердят данное утверждение.
Пересказывать википедию я не буду. Поэтому сразу же двинемся дальше и пройдемся по ключевым отличиям и преимуществам.
▌ Эпизод I: Bytecode
CIL (Common Intermediate Language, он же MSIL, он же просто IL) – является байт-кодом с полиморфными (обобщенными) инструкциями.
Так, если в Java используется отдельная инструкция для каждого типа операций с различными типами (например: fadd – сложение 2-х float, iadd – сложение 2-х integer), то в CIL для каждого вида операций существует лишь одна инструкция с полиморфными параметрами (например, существует только одна инструкция – add, производящая сложение и float, и integer). Вопрос решения генерации соответствующих x86-инструкций ложится на JIT.
Количество инструкций у обеих платформ примерно одинаковое. Сравнивая список команд байт-кода Java и CIL, видно, что 206 у Java, и 232 — CIL, однако не забываем, что у Java многие команды просто повторяют функционал друг друга.
▌ Эпизод III: Generics (parameterized types || parametric polymorphism)
Как известно, в Java используется механизм type erasure, т.е. поддержка generics обеспечивается лишь компилятором, но не рантаймом, и после компиляции информация о самом типе не будет доступна.
Выведет true.
При этом вместо обобщенного типа T создается экземпляр объекта типа java.lang.Object.
Будет преобразован к виду:
Таким образом, вся политика безопасности типов разрушается моментально.
- Поддержка generics на уровне Common Type System для кросс-языкового взаимодействия
- Полная поддержка со стороны Reflection API
- Добавление новых классов/методов в базовые классы (Base Class Library)
- Изменения в самом формате и таблицах метаданных
- Изменения в алгоритме выделения памяти рантаймом
- Добавления новых структур данных
- Поддержка generics со стороны JIT (code-sharing)
- Изменения в формате CIL (новые инструкции байт-кода)
- Поддержка со стороны верификатора CIL-кода
▌ Эпизод IV: Types
Java является полностью ОО-языком. С этим можно поспорить. И вот почему: примитивные типы (integer, float и т.п.) не наследуются от java.lang.Object. Поэтому generics в Java не поддерживают primitive types.
А ведь в по-настоящему ОО-языке everything is object.
Это не единственное ограничение. Также невозможно создать собственные примитивные типы.
Если в Java необходимо писать так:
Итак, value type – аналог primitive type из Java. Однако наследуется от System.Object, живет не в куче, а в стеке (а теперь оговорка: расположение value type зависит от его жизненного цикла, например, при участии в замыкании автоматически происходит boxing).
Reference type – представляет собой то же самое, что и reference types в Java.
Очень похоже на C++ код, не так ли?
- Свойства (в том числе автоматические)
- Делегаты
- События
- Анонимные методы
- Лямбда-выражения
- LINQ
- Expression Trees
- Анонимные классы
- Мощный вывод типов
- Перегрузка операторов
- Indexers
- …еще много чего
Будет преобразовано к виду:
Делегаты являются аналогами указателей на методы в C/C++. Однако являются типобезопасными. Их главное предназначение – callback функции, а также работа с событиями.
Данный подход коренным образом отличается от проекта Da Vinci для Java, т.к. в последнем пытаются расширить саму VM.
События необходимы для реализации событийно-ориентированного программирования. Конечно, можно обойтись и EventDispatcher’ом, или паттерном Publisher/Subscriber. Однако нативная поддержка со стороны языка дает весомые преимущества. Одним из которых является типобезопасность.
Анонимные методы существенно упрощают жизнь – структура класса остается чистой, т.е. не нужно создавать отдельные лишние методы в самом классе.
Изменим вышеприведенный пример с бинарными операциями с использованием анонимных методов:
Не правда ли более коротко и чисто?
Рассмотрим теперь лямбда-выражения.
Лямбда-выражение — это анонимная функция, которая содержит выражения и операторы, а также может использоваться для создания делегатов или дерева выражений.
А как же будет выглядеть пример с событиями? Очень просто:
Лямбда-выражения, а вместе с ними и деревья выражений были созданы вместе с LINQ (Language Integrated Query).
Все еще не знакомы с LINQ? Хотите увидеть как будет выглядеть знаменитый MapReduce на LINQ?
Или же использовать SQL-подобный синтаксис:
В этом примере мы видим и LINQ (GroupBy().Select().Where() и т.д.), и анонимные классы –
Хм…что же еще здесь используется? Ответ прост – мощная система вывода типов.
Главную роль здесь играет ключевое слово var. C++ 11 имеет аналогичную конструкцию auto.
Так без вывода типов нам пришлось бы писать так:
[Данный метод сгенерировал за нас компилятор]
▌ Заключение
Надеюсь, что моя статья помогла решить (хотя бы немного) вопрос разности и языков, и платформ.
Читайте также: