Чем word отличается от int

Обновлено: 07.07.2024

Если вы уверенно сможете правильно ответить на эти вопросы, тогда эта статья не для вас. В противном случае десять минут, потраченные на её чтение, будут весьма полезны.

  1. Знаковые оба.
  2. Законны оба.
  3. 8.
  4. 2147483647. -2147483648.
  5. Конечно, Кэп.
  1. char — не регламентируется, int — знаковый.
  2. Для int — законно, а для char — нет.
  3. Не менее 8.
  4. 32767. -32767
  5. Вообще говоря, нет.

Про 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.

Так без вывода типов нам пришлось бы писать так:


[Данный метод сгенерировал за нас компилятор]

▌ Заключение

Надеюсь, что моя статья помогла решить (хотя бы немного) вопрос разности и языков, и платформ.

Читайте также: