Що повинно означати кастинг?


18

При кодуванні на мовах низького рівня, таких як CI, виявляється, що іноді кастинг означає "переінтерпретувати ці байти так, як ніби він був завжди іншого типу", а в інший час як "інтелектуально перетворити це значення в інший тип".

Яке початкове значення цього слова і чи є узгодженість, коли слід очікувати конверсії та коли очікувати сирої реінтерпретації?


що у статті Вікіпедії ви не розумієте? « Перетворення типу , типажів і примусі різні способи, явно чи неявно, змінюючи об'єкт одного типу даних в інший ... Кожна мова програмування має свої власні правила про те , як типи можуть бути перетворені ...»
комар

Оригінальне значення "кинути" не має нічого спільного з програмуванням, дивіться тут merriam-webster.com/dictionary/cast
Doc Brown

1
Багато (в основному з точки зору керованої мови) в блозі Еріка
Ліпперта в

1
@gnat: Я не впевнений, чи це серйозне питання чи просто спроба тролінгу. Але я хотів би знати, як знати, що буде робити компілятор: конвертувати, передати чи примусити? Які правила великого пальця?
Олександр Торстлінг

1
@DocBrown Я думаю, що термін castв обчислювальному сенсі більше схожий на лиття в металургійному сенсі, завдяки якому форма розплавленого металу перетворюється під час виливання у форму: britannica.com/EB
KChaloux

Відповіді:


10

Кастинг на C унікальний, зовсім не схожий на інші мови. Це також ніколи не є розумним.

Кастинг на C перетворює значення з одного типу в інший, використовуючи ретельно визначені правила. Якщо вам справді потрібно знати, прочитайте стандарт. Інакше основні моменти:

  1. Перетворення між цілими типами зберігає значення, якщо це можливо. Якщо місце призначення має більше бітів, це розширюється і, як правило, безпечно, але може включати розширення знаків. Якщо вужчі, біти будуть втрачені.
  2. Перетворення між типами вказівника зберігає значення вказівника, але результати часто не визначені, часто не переносяться і часто корисні для розширених сценаріїв.
  3. Перетворення між цілими типами та покажчиками є нормальним, якщо ціле число є достатньо великим, і зберігається бітова модель (все, що це може означати). Якщо ціле число занадто мало, результат не визначений, але не є корисним. Як правило, "long" достатньо широкий для "void *", але жодних гарантій! Покажчики, створені таким чином, можуть бути недійсними в усіх видах цікавих способів.
  4. Перетворення між плаваючими і цілими типами - це арифметичні перетворення, визначені відповідною процедурою бібліотеки (з усіченням, а не округленням).
  5. Ви можете скинути повернене значення функції до недійсної. Я ніколи не маю. Це нічого не робить.

Деякі касти застосовуються неявно, а в деяких із них компілятор видасть попередження. Найкраще прислухайтеся до попереджень!

Визначення словника для кастингу найкраще ігнорувати як непотрібне. Багато хто в ролях краще описується термінами конверсія або примус, тому їх теж варто знати.

C ++ набагато складніше, але ви цього не запитували, чи не так?


Мене цікавлять великі правила, а не мізерні деталі, але мене цікавлять інші мови, ніж C, якщо це допомагає очистити речі.
Олександр Торстлінг

2
Те, що я дав тут, є таким же загальним, як і розумним. Для написання справжнього, професійного коду низького рівня C / C ++ важлива детальна деталізація. Більшість мов просто не мають такого типу при перетворенні типу. Вибачте, якщо це не вирішує вашу проблему.
david.pfx

За винятком того, що перетворення з T*в void*і назад завжди добре визначені.
Майлз Рут

@Miles: Власне, для збереження вихідного значення вказівника потрібне перетворення T * в будь-який U * і назад. У своїй відповіді я сказав лише: "часто невизначений", щоб це було коротко, "оскільки деякі деталі дуже брудні.
david.pfx

1
@supercat: Див. n1570 S6.3.2.3. Перетворення / кругові відключення між T *, U * і void * завжди зберігає значення вказівника лише за одним винятком. Якщо будь-який T * неправильно вирівняний, це не визначена поведінка. Я приймаю вашу думку, але лише в тій мірі.
david.pfx

2

Ця частина словника Вебстера дає належне визначення:

a: надати форму (речовині), виливаючи рідку або пластичну форму у форму і даючи твердіти без тиску
b: формуватися цим процесом

Отже, перед тим, як робити кастинг, ваш "об'єкт" (не буквально об'єкт OOP) має задану форму (тип). Коли ви знову відлиєте його, тобто "залийте бетон" навколо нього, щоб він набув нової форми, це те, що ви робите з литтям. У вас є число як шестикутне ціле число, і після відливання ви отримаєте рядок у формі прямокутника.


2
Також : "Призначити певну роль (акторові)".
Келлі Томас

Так. Я впевнений, що це найкраще. +1.
david.pfx

2

Може бути корисним розділити C Casts на дві групи:

  1. Числові касти - перетворять число між одним представленням в інше, намагаючись зберегти значення. Наприклад - (int)3.1було б 3. Існують точні правила, що визначають, що відбувається, коли точне значення не вдається зберегти.

  2. Відкидання покажчиків - Зберігайте адресу пам'яті, але змініть спосіб її відміни. Наприклад, for float x=3.5, *(int *)&xwill give 1080033280- це ціле число представлене тим самим бітовим малюнком, який представляє float 3.5.


Keep the memory address, but change the way it's dereferenced.Розмежування вказуваного типу покажчика не визначено. Стандарт лише гарантує, що перекидання з " A *на" B *та "назад" створюватиме те саме A *, що, можливо, не було дійсним для відновлення 1-го місця - або що, якщо B *це "a" char *, воно може використовуватися для зчитування представлення об'єктів будь-якого типу. Для всіх інших типів B *вказівник перенаправлення є типовим покаранням, UB та порушує суворий псевдонім. У будь-якому випадку, навіть якщо компілятор не зіпсував вищезгаданий приклад 2 з цієї причини, ви робите непридатні припущення щодо бітових шаблонів
underscore_d

1
cast (v): to receive form in a mold

У C ++ різного роду касти можна зробити більш явними, маючи на reinterpret_castувазі "ставитися до цих байтів так, ніби вони вже були цією іншою справою". У C ви можете зробити це абсолютно явним, використовуючи a union, кастинг з (type)оператором намагатиметься зберегти результат чисельно еквівалентним, аж до втрати точності.


2
У C покажчики вказівки завжди переосмислюються, а цінні касти завжди зберігають значення якнайкраще. У C ++ є кілька способів зробити покажчик покажчиків, саме тому існують більш чіткі типи викликів.
Ян Худек

C-семантика покажчиків не обов'язково "переосмислюється". Було б законно, щоб процесор, який використовував адресування слів, але хотів красиво взаємодіяти з байтовим кодом, мав, int*що це було одне слово, а а - char*це два слова [другий байт вибирав високий або низький байт слова]. Передача на (int*)to (char*)вимагає додавання додаткового слова, яке має бути будь-яким значенням, яке б визначало перший байт int.
суперкат
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.