Jump to content

Преобразование типов

(Перенаправлено из состава Const )

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

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

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

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

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

Явное приведение типов на разных языках

[ редактировать ]

Ada предоставляет общую библиотечную функцию Unchecked_Conversion. [8]

C-подобные языки

[ редактировать ]

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

[ редактировать ]

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

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

double  d;
long    l;
int     i;

if (d > i)   d = i;
if (i > l)   l = i;
if (d == l)  d *= 2;

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

#include <stdio.h>

int main(void)
{
    int i_value   = 16777217;
    float f_value = 16777216.0;
    printf("The integer is: %d\n", i_value);
    printf("The float is:   %f\n", f_value);
    printf("Their equality: %d\n", i_value == f_value);
}

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

The integer is: 16777217
The float is: 16777216.000000
Their equality: 1

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

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

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

Одним из особых случаев неявного преобразования типов является повышение типа, при котором объект автоматически преобразуется в другой тип данных, представляющий надмножество исходного типа. Расширения обычно используются с типами, меньшими, чем собственный тип арифметико-логического устройства (АЛУ) целевой платформы, перед арифметическими и логическими операциями, чтобы сделать такие операции возможными или более эффективными, если АЛУ может работать более чем с одним типом. В C и C++ такое повышение выполняется для объектов логического, символьного, широкого символьного, перечисляемого и короткого целочисленного типов, которые повышаются до int, а также для объектов типа float, которые повышаются до double. В отличие от некоторых других преобразований типов, повышения никогда не теряют точности и не изменяют значение, хранящееся в объекте.

На Яве :

int x = 3;
double y = 3.5;
System.out.println(x + y); // The output will be 6.5

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

[ редактировать ]

Явное преобразование типов, также называемое приведением типов, — это преобразование типов, которое явно определяется внутри программы (вместо того, чтобы выполняться автоматически в соответствии с правилами языка для неявного преобразования типов). Его запрашивает пользователь в программе.

double da = 3.3;
double db = 3.3;
double dc = 3.4;
int result = (int)da + (int)db + (int)dc; // result == 9
// if implicit conversion would be used (as with "result = da + db + dc"), result would be equal to 10

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

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

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

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

Animal animal = new Cat();

Bulldog b = (Bulldog) animal;  // if (animal is Bulldog), stat.type(animal) is Bulldog, else an exception
b = animal as Bulldog;         // if (animal is Bulldog), b = (Bulldog) animal, else b = null

animal = null;
b = animal as Bulldog;         // b == null

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

Animal* animal = new Cat;

Bulldog* b = static_cast<Bulldog*>(animal); // compiles only if either Animal or Bulldog is derived from the other (or same)
b = dynamic_cast<Bulldog*>(animal);         // if (animal is Bulldog), b = (Bulldog*) animal, else b = nullptr

Bulldog& br = static_cast<Bulldog&>(*animal); // same as above, but an exception will be thrown if a nullptr was to be returned
                                              // this is not seen in code where exception handling is avoided

delete animal; // always free resources
animal = nullptr;
b = dynamic_cast<Bulldog*>(animal);         // b == nullptr

Эйфелева

[ редактировать ]

В Эйфеле понятие преобразования типов интегрировано в правила системы типов. Правило назначения гласит, что назначение, например:

x := y

допустимо тогда и только тогда, когда тип его исходного выражения, 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, должно использовать строковый класс .NET ( System.String) во многих случаях, например, при вызове методов .NET, которые ожидают передачи элементов типа .NET в качестве аргументов. Таким образом, преобразование этих типов туда и обратно должно быть максимально простым.

    my_string: STRING_8                 -- Native Eiffel string
    my_system_string: SYSTEM_STRING     -- Native .NET string

        ...

            my_string := my_system_string

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

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

    class STRING_8
        ...
    create
        make_from_cil
        ...
    convert
        make_from_cil ({SYSTEM_STRING})
        ...

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

            my_string := my_system_string

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

            create my_string.make_from_cil (my_system_string)

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

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

            my_system_string := my_string

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

    class STRING_8
        ...
    create
        make_from_cil
        ...
    convert
        make_from_cil ({SYSTEM_STRING})
        to_cil: {SYSTEM_STRING}
        ...

Задание:

            my_system_string := my_string

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

            my_system_string := my_string.to_cil

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

Ржавчина

[ редактировать ]

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

let x = 1000;
println!("1000 as a u16 is: {}", x as u16);

Тип утверждения

[ редактировать ]

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

Машинопись

[ редактировать ]

В TypeScript утверждение типа выполняется с помощью as ключевое слово: [11]

const myCanvas = document.getElementById("main_canvas") as HTMLCanvasElement;

В приведенном выше примере document.getElementById объявлено, что он возвращает HTMLElement, но вы знаете, что он всегда возвращает HTMLCanvasElement, который является подтипом HTMLElement, в этом случае. Если это не так, последующий код, основанный на поведении HTMLCanvasElement не будет работать корректно, поскольку в Typescript нет проверки утверждений типа во время выполнения.

В Typescript нет общего способа проверить, относится ли значение к определенному типу во время выполнения, поскольку нет поддержки типов во время выполнения. Однако можно написать пользовательскую функцию, которая будет сообщать пользователю компилятору, если значение имеет определенный тип «нет». Такая функция называется typeguard и объявляется с возвращаемым типом x is Type, где x является параметром или this, вместо boolean.

Это позволяет содержать утверждения небезопасного типа в функции проверки, а не разбрасывать их по базе кода.

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

t := i.(T)

Утверждения этого типа сообщают системе, что i имеет тип T. Если это не так, он паникует.

Неявное приведение с использованием нетегированных объединений

[ редактировать ]

Многие языки программирования поддерживают типы объединения , которые могут содержать значения нескольких типов. Немаркированные объединения предусмотрены в некоторых языках со свободной проверкой типов, таких как C и PL/I , а также в исходном языке Pascal . Их можно использовать для интерпретации битовой комбинации одного типа как значения другого типа.

Проблемы безопасности

[ редактировать ]

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

См. также

[ редактировать ]
  1. ^ Jump up to: а б с Мехротра, Дирадж (2008). Информатика С. Чанда . С. Чанд. стр. 81–83. ISBN  978-8121929844 .
  2. ^ Языки программирования — Проектирование и конструкции . Публикации Лакшми. 2013. с. 35. ISBN  978-9381159415 .
  3. ^ Jump up to: а б Рейли, Эдвин (2004). Краткая энциклопедия информатики . Джон Уайли и сыновья. стр. 82, 110 . ISBN  0470090952 .
  4. ^ Фентон, Стив (2017). Pro TypeScript: разработка JavaScript в масштабе приложения . Апресс. стр. XXII. ISBN  978-1484232491 .
  5. ^ «PHP: Жонглирование типами — Руководство» . php.net . Проверено 27 января 2019 г.
  6. ^ Jump up to: а б Олссон, Микаэль (2013). Краткий справочник по синтаксису C++ . Апресс. стр. 87–89. ISBN  978-1430262770 .
  7. ^ Крузе, Рудольф; Боргельт, Кристиан; Брауне, Кристиан; Мостагим, Саназ; Штайнбрехер, Матиас (16 сентября 2016 г.). Вычислительный интеллект: методологическое введение . Спрингер. п. 269. ИСБН  978-1447172963 .
  8. ^ «Непроверенные преобразования типов» . Информационный центр Ады . Проверено 11 марта 2023 г.
  9. ^ Мессенбёк, Ханспетер (25 марта 2002 г.). «Продвинутый C#: проверенное приведение типов» (PDF) . Институт системного программного обеспечения, Университет Иоганна Кеплера в Линце, факультет компьютерных наук. п. 5 . Проверено 4 августа 2011 г. в учебнике по C#
  10. ^ «Литье — ржавчина на примере» . doc.rust-lang.org .
  11. ^ " "Машинописная документация" " .
  12. ^ « Экскурсия по Го » .
  13. ^ Jon Erickson Hacking, 2nd Edition: The Art of Exploitation 2008 1593271441 p51 «Приведение типов — это просто способ временно изменить тип данных переменной, несмотря на то, как он был первоначально определен. Когда переменная приводится к другому типу, компилятор по сути сказано обрабатывать эту переменную так, как если бы это был новый тип данных, но только для этой операции. Синтаксис приведения типов следующий: (typecast_data_type) переменная ..."
  14. ^ Арпита Гопал Лупа C 2009 8120338618 стр. 59 «Из вышесказанного ясно, что использование приведения типов заключается в том, чтобы заставить переменную одного типа действовать как другой тип для одной операции. Таким образом, используя эту возможность приведения типов, можно создавать символы ASCII путем приведения целого числа к типу. его ..."
[ редактировать ]
Arc.Ask3.Ru: конец переведенного документа.
Arc.Ask3.Ru
Номер скриншота №: d1b520e32e43316fcd201d7dfcb23e5e__1721778120
URL1:https://arc.ask3.ru/arc/aa/d1/5e/d1b520e32e43316fcd201d7dfcb23e5e.html
Заголовок, (Title) документа по адресу, URL1:
Type conversion - Wikipedia
Данный printscreen веб страницы (снимок веб страницы, скриншот веб страницы), визуально-программная копия документа расположенного по адресу URL1 и сохраненная в файл, имеет: квалифицированную, усовершенствованную (подтверждены: метки времени, валидность сертификата), открепленную ЭЦП (приложена к данному файлу), что может быть использовано для подтверждения содержания и факта существования документа в этот момент времени. Права на данный скриншот принадлежат администрации Ask3.ru, использование в качестве доказательства только с письменного разрешения правообладателя скриншота. Администрация Ask3.ru не несет ответственности за информацию размещенную на данном скриншоте. Права на прочие зарегистрированные элементы любого права, изображенные на снимках принадлежат их владельцам. Качество перевода предоставляется как есть. Любые претензии, иски не могут быть предъявлены. Если вы не согласны с любым пунктом перечисленным выше, вы не можете использовать данный сайт и информация размещенную на нем (сайте/странице), немедленно покиньте данный сайт. В случае нарушения любого пункта перечисленного выше, штраф 55! (Пятьдесят пять факториал, Денежную единицу (имеющую самостоятельную стоимость) можете выбрать самостоятельно, выплаичвается товарами в течение 7 дней с момента нарушения.)