Из Википедии, бесплатной энциклопедии
Перейти к навигации Перейти к поиску

В информатике , типа преобразовании , [1] [2] типа литья , [1] [3] типа принуждения , [3] и типа жонглирование [4] [5] различные пути изменения в экспрессии от одного типа данных к другому . Примером может служить преобразование целочисленного значения в значение с плавающей запятой или его текстовое представление в виде строки и наоборот. Преобразования типов могут использовать преимущества определенных функций иерархий типов или представлений данных.. Два важных аспекта преобразования типа являются происходит ли это неявно (автоматически) или в явном виде , [1] [6] , и является ли базовое представление данных преобразуются из одного представления в другое, или данное представление является лишь переосмыслено как представление другого тип данных. [6] [7] Как правило, можно преобразовывать как примитивные, так и составные типы данных .

Каждый язык программирования имеет свои собственные правила преобразования типов. Языки со строгой типизацией обычно выполняют мало неявных преобразований и препятствуют повторной интерпретации представлений, в то время как языки со слабой типизацией выполняют множество неявных преобразований между типами данных. Слабый язык типизации часто позволяет заставить компилятор произвольно интерпретировать элемент данных как имеющий разные представления - это может быть неочевидная ошибка программирования или технический метод для непосредственной работы с базовым оборудованием.

В большинстве языков слово принуждение используется для обозначения неявного преобразования либо во время компиляции, либо во время выполнения . Например, в выражении, сочетающем целые числа и числа с плавающей запятой (например, 5 + 0,1), компилятор автоматически преобразует целочисленное представление в представление с плавающей запятой, чтобы дроби не терялись. Явные преобразования типов указываются либо путем написания дополнительного кода (например, добавления идентификаторов типа или вызова встроенных подпрограмм ), либо путем кодирования подпрограмм преобразования для компилятора, который в противном случае остановился бы из-за несоответствия типов.

В большинстве Algol -подобных языков, таких как Pascal , Modula-2 , Ada и Delphi , преобразования и литья отчетливо различные концепции. В этих языках преобразование относится либо к неявному, либо к явному изменению значения из одного формата хранения данных в другой, например 16-битное целое число в 32-битное целое число. Потребности в хранении могут измениться в результате преобразования, включая возможную потерю точности или усечение. Слово литой , с другой стороны, относится к явным образом изменяя интерпретацию в битовой комбинациипредставление значения от одного типа к другому. Например, 32 смежных бита можно рассматривать как массив из 32 логических значений, 4-байтовую строку, 32-битное целое число без знака или значение с плавающей запятой одинарной точности IEEE. Поскольку хранимые биты никогда не изменяются, программист должен знать подробности низкого уровня, такие как формат представления, порядок байтов и потребности выравнивания, чтобы их можно было осмысленно преобразовать.

В C семействе языков и АЛГОЛА 68 , слово литой , как правило , относится к явным преобразованию типа (в отличие от неявного преобразования), в результате чего некоторые двусмысленностей об этом , является ли реинтерпретация битового шаблона или представление реальных данных конверсия. Более важным является множество способов и правил, которые применяются к тому, какой тип данных (или класс) находится с помощью указателя, и как указатель может быть скорректирован компилятором в таких случаях, как наследование объекта (класса).

Сравнение языков [ править ]

C-подобные языки [ править ]

Неявное преобразование типа [ править ]

Неявные преобразования типов, также известные как принуждение , является автоматическим преобразованием типа по компилятору . Некоторые языки программирования позволяют компиляторам обеспечивать принуждение; другие требуют этого.

В выражении смешанного типа данные одного или нескольких подтипов могут быть преобразованы в супертип по мере необходимости во время выполнения, чтобы программа работала правильно. Например, следующий код допустимого языка C :

двойной  d ; длинный  l ; int  i ;если  ( d  >  i )  d  =  i ; если  ( i  >  l )  l  =  i ; если  ( d  ==  l )  d  * =  2 ;

Хотя d , l и i принадлежат к разным типам данных, они будут автоматически преобразовываться в одинаковые типы данных каждый раз, когда выполняется сравнение или присваивание. Это поведение следует использовать с осторожностью, поскольку могут возникнуть непредвиденные последствия . Данные могут быть потеряны при преобразовании представлений с плавающей запятой в целое число, поскольку дробные компоненты значений с плавающей запятой будут усечены (округлены в сторону нуля). И наоборот, точность может быть потеряна при преобразовании представлений из целых чисел в числа с плавающей запятой, поскольку тип с плавающей запятой может быть неспособен точно представить целочисленный тип. Например, это может быть IEEE 754floatтип одинарной точности, который не может точно представлять целое число 16777217, в то время как 32-разрядный целочисленный тип может. Это может привести к неинтуитивному поведению, о чем свидетельствует следующий код:

#include  <stdio.h>int  main ( void ) {  int  i_value  =  16777217 ;  float  f_value  =  16777216.0 ;  printf ( "Целое число:% d \ n " ,  i_value );  printf ( "Число с плавающей запятой:% f \ n " ,  f_value );  printf ( "Их равенство:% d \ n " ,  i_value  ==  f_value ); }

В компиляторах, которые реализуют числа с плавающей запятой как одинарную точность IEEE, а целые числа - как минимум 32 бита, этот код даст такую ​​специфическую распечатку:

Целое число: 16777217Число с плавающей запятой: 16777216.000000Их равенство: 1

Обратите внимание, что 1 представляет равенство в последней строке выше. Это странное поведение вызвано неявным преобразованием i_valueв float при сравнении с f_value. Преобразование приводит к потере точности, что приводит к равенству значений перед сравнением.

Важные выводы:

  1. floatдля intпричин усечения , то есть удаление дробной части.
  2. doubleдо floatпричин округления цифр.
  3. longчтобы intпричины отсева избыточных битов высших порядков.
Повышение типа [ править ]

Одним из особых случаев неявного преобразования типа является повышение типа, когда компилятор автоматически расширяет двоичное представление объектов целочисленных типов или типов с плавающей запятой. Повышения обычно используются с типами, меньшими, чем собственный тип арифметико-логического блока (ALU) целевой платформы , перед арифметическими и логическими операциями, чтобы сделать такие операции возможными, или более эффективными, если ALU может работать с более чем одним типом. C и C ++ выполняют такое продвижение для объектов типа boolean, character, wide character, enumeration и short integer, которые повышаются до int, а также для объектов типа float, которые повышаются до double. В отличие от некоторых других преобразований типов, рекламные акции никогда не теряют точности и не изменяют значение, хранящееся в объекте.

В Java :

int  x  =  3 ; двойной  y  =  3,5 ; Система . из . println ( х  +  у );  // Результат будет 6.5

Явное преобразование типа [ править ]

Явное преобразование типа - это преобразование типа, которое явно определяется в программе (вместо того, чтобы выполняться компилятором для неявного преобразования типа). Он определяется пользователем в программе.

двойной  da  =  3,3 ; двойной  db  =  3,3 ; двойной  dc  =  3,4 ; int  результат  =  ( int ) da  +  ( int ) db  +  ( int ) dc ;  // результат == 9 // если бы использовалось неявное преобразование (как с "result = da + db + dc"), результат был бы равен 10

Есть несколько видов явного преобразования.

проверил
Перед выполнением преобразования выполняется проверка во время выполнения, чтобы увидеть, может ли целевой тип содержать исходное значение. В противном случае возникает состояние ошибки.
не отмечен
Никакой проверки не производится. Если тип назначения не может содержать исходное значение, результат не определен.
битовая комбинация
Необработанное битовое представление источника копируется дословно и повторно интерпретируется в соответствии с типом назначения. Этого также можно добиться с помощью псевдонима .

В объектно-ориентированных языках программирования объекты также могут быть понижены  : ссылка базового класса приводится к одному из его производных классов.

C # и C ++ [ править ]

В C # преобразование типа может быть выполнено безопасным или небезопасным (т. Е. C-подобным) способом, первый из которых называется приведением типа с проверкой . [8]

Животное  животное  =  новый  Кот ();Бульдог  b  =  ( Бульдог )  животное ;  // если (животное - Бульдог), stat.type (животное) - Бульдог, иначе исключение b  =  животное  как  Бульдог ;  // если (животное это Бульдог), b = (Бульдог) животное, иначе b = nullanimal  =  null ; b  =  животное  как  Бульдог ;  // b == null

В C ++ аналогичного эффекта можно добиться, используя синтаксис приведения в стиле C ++ .

Животное *  животное  =  новый  Кот ;Бульдог *  b  =  static_cast < Бульдог *> ( животное );  // компилируется, только если Animal или Bulldog являются производными от другого (или того же самого) b  =  dynamic_cast < Bulldog *> ( animal );  // если (животное это Бульдог), b = (Бульдог *) животное, иначе b = nullptrБульдог &  br  =  static_cast < Бульдог &> ( * животное );  // то же, что и выше, но будет сгенерировано исключение, если должен был быть возвращен nullptr  // это не видно в коде, где избегается обработка исключений animal  =  nullptr ; b  =  dynamic_cast < Бульдог *> ( животное );  // b == nullptrудалить  животное ;  // всегда свободные ресурсы

Эйфель [ править ]

В Eiffel понятие преобразования типов интегрировано в правила системы типов. Правило присвоения гласит, что такое задание, как:

х  : =  у

допустимо тогда и только тогда, когда тип его исходного выражения yв этом случае совместим с типом его целевой сущности xв этом случае. В этом правиле, совместимом с помощью , что тип выражения источника либо соответствует или обращенным к что мишени. Соответствие типов определяется знакомыми правилами полиморфизма в объектно-ориентированном программировании . Например, в приведенном выше назначении тип yсоответствует типу, xесли класс, на котором yоснован, является потомком того, на котором xоснован.

Определение преобразования типов в Eiffel [ править ]

Действия преобразования типа в Eiffel, в частности преобразование в и преобразование из , определены как:

Тип, основанный на классе CU, преобразуется в тип T на основе класса CT (и T преобразуется из U), если либо

CT имеет процедуру преобразования, использующую U в качестве типа преобразования, или
В CU есть список запроса преобразования T в качестве типа преобразования

Пример [ править ]

Eiffel - это полностью совместимый язык для Microsoft .NET Framework . До разработки .NET у Eiffel уже были обширные библиотеки классов. Использование библиотек типов .NET, особенно с часто используемыми типами, такими как строки, создает проблему преобразования. Существующее программное обеспечение Eiffel использует строковые классы (например, STRING_8) из библиотек Eiffel, но программное обеспечение Eiffel, написанное для .NET, System.Stringво многих случаях должно использовать строковый класс .NET ( ), например, при вызове методов .NET, которые ожидают элементы .NET. тип, передаваемый в качестве аргументов. Таким образом, преобразование этих типов туда и обратно должно быть как можно более плавным.

 my_string :  STRING_8  - Собственная строка Eiffel  my_system_string :  SYSTEM_STRING  - Собственная строка .NET ... my_string  : =  my_system_string

В приведенном выше коде объявлены две строки, по одной каждого типа ( SYSTEM_STRINGэто совместимый с Eiffel псевдоним для System.String). Поскольку System.Stringне соответствует STRING_8, то указанное выше присвоение допустимо, только если System.Stringпреобразовано в STRING_8.

Класс Eiffel STRING_8имеет процедуру преобразования make_from_cilдля объектов типа System.String. Процедуры преобразования также всегда обозначаются как процедуры создания (аналогично конструкторам). Ниже приводится отрывок из STRING_8занятия:

 класс  STRING_8  ...  создать  make_from_cil  ...  преобразовать  make_from_cil  ({ SYSTEM_STRING })  ...

Наличие процедуры преобразования делает присвоение:

 my_string  : =  my_system_string

семантически эквивалентен:

 создать  my_string . make_from_cil  ( my_system_string )

в котором my_stringсоздается как новый объект типа STRING_8с содержимым, эквивалентным содержимому my_system_string.

Чтобы обработать назначение с перевернутыми исходным источником и целью:

 my_system_string  : =  моя_строка

класс STRING_8также содержит запрос преобразования, to_cilкоторый создаст System.Stringиз экземпляра STRING_8.

 класс  STRING_8  ...  создать  make_from_cil  ...  преобразовать  make_from_cil  ({ SYSTEM_STRING })  в_cil :  { SYSTEM_STRING }  ...

Назначение:

 my_system_string  : =  моя_строка

тогда становится эквивалентным:

 my_system_string  : =  моя_строка . to_cil

В Eiffel настройка преобразования типов включается в код класса, но затем кажется, что это происходит автоматически, как явное преобразование типов в клиентском коде. Включает не только присвоения, но и другие типы вложений, такие как подстановка аргумента (параметра).

Ржавчина [ править ]

Rust не обеспечивает неявного преобразования (принуждения) типов между примитивными типами. Но явное преобразование типа (приведение) можно выполнить с помощью asключевого слова. [9]

println! ( "1000 как u16 равно: {}" , 1000 как u16 );   

Проблемы безопасности [ править ]

При взломе приведение типов - это неправильное использование преобразования типа для временного изменения типа данных переменной по сравнению с тем, как он был изначально определен. [10] Это предоставляет возможности для хакеров, поскольку при преобразовании типа после «преобразования типа» переменной в другой тип данных компилятор будет рассматривать эту взломанную переменную как новый тип данных для этой конкретной операции. [11]

См. Также [ править ]

  • Понижение
  • Информация о типе времени выполнения # динамическое приведение и приведение Java
  • Набросок типа

Ссылки [ править ]

  1. ^ a b c Mehrotra, Dheeraj (2008). Компьютерные науки С. Чанда . С. 81–83. ISBN 978-8121929844.
  2. ^ Языки программирования - Дизайн и конструкции . 2013. с. 35. ISBN 978-9381159415.
  3. ^ a b Рейли, Эдвин (2004). Краткая энциклопедия компьютерных наук . С.  82, 110 . ISBN 0470090952.
  4. ^ Фентон, Стив (2017). Pro TypeScript: разработка на JavaScript в масштабе приложения . стр. xxiii. ISBN 978-1484232491.
  5. ^ «PHP: Типаж - Руководство» . php.net . Проверено 27 января 2019 .
  6. ^ a b Олссон, Микаэль (2013). Краткий справочник по синтаксису C ++ . С. 87–89. ISBN 978-1430262770.
  7. ^ Круз, Рудольф; Боргельт, Кристиан; Браун, Кристиан; Мостагим, Саназ; Штейнбрехер, Маттиас (16 сентября 2016 г.). Вычислительный интеллект: методологическое введение . п. 269. ISBN. 978-1447172963.
  8. ^ Mössenböck, Hanspeter (25 марта 2002). «Advanced C #: Checked Type Casts» (PDF) . Institut für Systemsoftware, Университет Йоханнеса Кеплера в Линце, Fachbereich Informatik. п. 5 . Проверено 4 августа 2011 года . в Учебнике C #
  9. ^ «Литье - пример ржавчины» . doc.rust-lang.org .
  10. ^ Jon Erickson Hacking, 2nd Edition: The Art of Exploitation 2008 1593271441 p51 «Приведение типов - это просто способ временно изменить тип данных переменной, несмотря на то, как он был первоначально определен. сказано обрабатывать эту переменную, как если бы это был новый тип данных, но только для этой операции. Синтаксис для преобразования типов следующий: (typecast_data_type) variable ... "
  11. ^ Арпита Гопал,увеличивающий C 2009 8120338618 p.59 "Из вышесказанного ясно, что использование преобразования типов состоит в том, чтобы сделать переменную одного типа, действуя как переменная другого типа для одной единственной операции. Таким образом, используя эту способность преобразования типов, возможно создание символов ASCII путем приведения целого числа к его ... "

Внешние ссылки [ править ]

  • Кастинг в Аде
  • Приведение в C ++
  • Справочное руководство по C ++ Почему я ненавижу операторы приведения в C ++, Дэнни Калев
  • Кастинг на Java
  • Неявные преобразования в C #
  • Неявное приведение типов на Cppreference.com
  • Статические и переинтерпретированные приведения в C ++
  • Повышающее и понижающее приведение в F #