1 / 1 / 0
Регистрация: 10.06.2013
Сообщений: 153
|
|
1 | |
Интерпретация переменной типа int как float16.08.2021, 20:49. Показов 8679. Ответов 53
Метки нет (Все метки)
0
|
16.08.2021, 20:49 | |
Ответы с готовыми решениями:
53
Это значение 5.9875e17 может быть сохранено в переменной, типа: int bool long short float? Как присвоить значение одного из элементов массива типа char переменной типа int? ОШИБКА [Error] cannot convert 'int*' to 'float*' for argument '1' to 'void Syma(float*,int*,int) Как сохранить float в переменной типа char? |
8972 / 4318 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
|
|||||||||||
16.08.2021, 21:53 | 21 | ||||||||||
Код
error: cannot convert ‘int*’ to ‘float*’ in initialization Код
warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing] наверное, ты имел ввиду:
трюк с объединением прокатывает на всех топовых компиляторах, тем не менее, формально, такой код содержит UB. лично я не стал бы ставить на такой код свою карьеру. зачем? если можно просто написать корректный код Добавлено через 6 минут в старых версиях с++ такое было невозможно провернуть не налетев на UB в новом с++ можно воспользоваться std::launder и это - единственный легальный способ реинтерпретировать "теплое" как "мягкое"
2
|
Модератор
|
|
16.08.2021, 21:58 | 23 |
- странно, что "грубейше неправильные" варианты тем не менее транслируются и успешно исполняются... Невольно возникает вопрос: почему язык не запрещает подобные конструкции? Или конкретнее - почему их пропускает компилятор?
0
|
8972 / 4318 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
|
||||||
16.08.2021, 22:00 | 24 | |||||
ну вот например
Код
0 1
0
|
Вездепух
12783 / 6662 / 1793
Регистрация: 18.10.2014
Сообщений: 16,849
|
|
16.08.2021, 22:06 | 25 |
Странно, что в форуме по С++ (пусть даже "для начинающих"), приводят в качестве "аргумента" такой детский лепет, как "эти варианты транслируются и успешно исполняются", как будто не понимают, что в С и С++ ваше "транслируются и успешно исполняются" не значит вообще ничего. Неужели за весь период существования этого форума даже завсегдатаи не смогли усвоить таких элементаранызх понятий, как неопределнное поведение?
В очередной раз спрошу с нескрываемым удивлением: вот это вот "транслируются и успешно исполняются" - это такой троллинг? Или здесь все действиельно настольоко запущено?
0
|
Вездепух
12783 / 6662 / 1793
Регистрация: 18.10.2014
Сообщений: 16,849
|
|
16.08.2021, 22:07 | 27 |
0
|
Модератор
|
|
16.08.2021, 22:12 | 28 |
TheCalligrapher, нет это не троллинг. Это вопрос к системе типов. Что стоило просто запретить подобные преобразования - и не было бы проблем. Если Вы мне объясните это (и я пойму), то буду благодарен... Когда меня убеждают - я соглашаюсь.
А вот когда мне заявляют менторским тоном "Это так и никак иначе", а на вопрос "Почему?" отвечают "Потому", то я упираюсь. Мне кажется, это мое право.
2
|
Вездепух
12783 / 6662 / 1793
Регистрация: 18.10.2014
Сообщений: 16,849
|
|
16.08.2021, 22:17 | 29 |
Нет, нельзя. Никакого отношения к прямой реинтерпретации
std::launder не имеет. Требование std::launder<T> - по целевому адресу располагается именно объект типа T .Добавлено через 4 минуты Невозможно на стадии компиляции "запретить преобразования", когда их корректность в общем случае зависит от факторов времени выполнения. Тема strict aliasing здесь обсуждадась много раз, в деталях. Зачем начинать сказку про белого бычка сначала? https://stackoverflow.com/ques... asing-rule https://habr.com/ru/company/otus/blog/442554/
2
|
8972 / 4318 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
|
|
16.08.2021, 22:19 | 30 |
0
|
4017 / 2563 / 430
Регистрация: 09.09.2017
Сообщений: 11,404
|
|||||||||||
17.08.2021, 10:12 | 32 | ||||||||||
Насколько я слышал, такой трюк использовался для быстрого вычисления обратного корня.
Сложно. Возможно, сломается на big/little endian, возможно с другим размером байта (стандарт дозволяет!) или еще при каких-то экзотических условиях. Потому что С (а следом и С++) заточены под ручную оптимизацию. Если программист знает, что делает - не надо ему мешать. Чуть упрощу ваш код:
Да все прекрасно понимают, что ваше "не значит ничего" не значит ничего. Если код транслируется и выполняется, то он транслируется и выполняется. И если он написан грамотно, то даже при наличии UB он продолжит транслироваться и выполняться как задумано, и им прекрасно можно пользоваться. Высокоуровневый ассемблер на то и высокоуровневый ассемблер чтобы давать возможность привязаться к особенностям конкретной платформы. Добавлено через 7 минут Так проблем и нет. Собственно, это одно из применений union'ов - интерпретация одной и той же кучки битов как разные типы. Один пример я уже описал - вычисление обратного корня. Второй - разбиение переменной на байты:
3
|
Злостный нарушитель
9542 / 5172 / 1182
Регистрация: 12.03.2015
Сообщений: 24,414
|
|
17.08.2021, 10:17 | 33 |
А чего, big/little endian распространяется не на все типы, а только на некоторые?
Я вчера так и не смог придумать пример UB для union {uint32_t x; float y; } . Если у int сменить порядок байтов, то у float он тоже должен измениться, разве нет?З.Ы. Хорошо, что я в своё время выбрал себе основным языком программирования язык со строгой типизацией.
0
|
4017 / 2563 / 430
Регистрация: 09.09.2017
Сообщений: 11,404
|
|
17.08.2021, 10:27 | 34 |
Не знаю. Но допускаю и такую возможность. Все-таки к байтам int'а можно обращаться по отдельности скажем для сложения, то float имеет смысл только как неделимая 32-битная сущность.
0
|
19409 / 10028 / 2443
Регистрация: 30.01.2014
Сообщений: 17,678
|
|
17.08.2021, 11:53 | 35 |
Это код из этой статьи, там же все объяснено, зачем и чего код демонстрирует.
Добавлено через 19 минут У вас тут смешаны понятия implementation-defined behavior, unspecified-behavior и undefined-behavior. Вся аргументация про высокоуровневый ассемблер и грамотный код справедлива только для первых двух понятий, но никак не для последнего. По его определению этот как раз не UB, потому что в этом случае по идентификатору мы точно понимаем что было записано при отправке события, и каст делаем именно к тому типу, который был записан. Т.е. тут нет type punning, и нет UB. Это применение union как раз является правильным во всех смыслах. Кроме того, как было уже сказано, в языке С разрешен type punning через union, в языке С это не UB. Кроме того, разработчики компиляторов С++ прекрасно знают, что трюк с реинтерпретацией через union очень популярен и в коде на С++, поэтому не реализуют никаких помех для его выполнения. Но это не делает код корректным, так же как не делает правильным забег через дорогу на красный свет, не смотря на то, что миллионы человек могут похвастаться, что с ними во время этого ничего не случилось. Не понятно почему аргументация к спецификации языка является "криками", ничего нового он не сказал, это все известно еще со времен C++98. Можно или нельзя в конкретном проекте плевать на несоответствие кода спецификации (в части корректности) - это вообще отдельный вопрос, который тут не обсуждался даже.
0
|
8972 / 4318 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
|
|
17.08.2021, 12:28 | 36 |
а зачем ты его начал чуть упрощать,
если ты даже не понял, зачем он был нужен?
0
|
4017 / 2563 / 430
Регистрация: 09.09.2017
Сообщений: 11,404
|
||||||
17.08.2021, 13:38 | 37 | |||||
Так ведь они и в реальности не слишком далеки друг от друга.
Приблизительно оно выглядит так:
Разумеется, делает. Да, в некоторых случаях возникнет проблема с переносимостью, но если разработчик сознательно использует подобные трюки, он ей сознательно жертвует ради скорости или читаемости. Равно как и переход дороги на красный свет, когда совершенно точно известно, что она перекрыта и движения на ней нет. Спецификация языка не говорит, что программа, содержащая UB, некорректна или тем более не должна компилироваться. Учитывая особенность С/С++, обойтись вот совсем без UB вряд ли возможно. Либо код станет совершенно нечитаемым и неэффективным. Уж слишком много они позволяют разработчикам компилятора. Ну а агрессивное навязывание своих фантазий, противоречащих реальному миру, и выглядит как бесполезные крики. Как полагались люди на безопасность переполнения знаковых чисел, так и будут. Как кастовали что угодно к чему угодно, так и будут. Как считали байт восьмибитным, так и будут считать. Не нравится - пусть идет в другие языки, где подобные вольности не дозволяются. Ну так разверните свою мысль. Что именно иллюстрирует ваш код и как он относится к вопросу Verevkin'а о касте int -> float?
0
|
19409 / 10028 / 2443
Регистрация: 30.01.2014
Сообщений: 17,678
|
|
17.08.2021, 13:49 | 38 |
Не замещайте общее частным.
Не говорит, но и гарантий корректности тоже не дает. Это прямо и означает, что программа в неопределенном состоянии. Про "компилироваться" там выше было совсем в другом контексте сказано. Не в том смысле, что не компилируется из-за UB. Там не компилировалось из-за неявного каста между несовместимыми типами. Добавлено через 1 минуту Для такого случая, когда есть layout-compatible, и С++ тоже разрешает это делать. Речь же не об этих случаях.
0
|
4017 / 2563 / 430
Регистрация: 09.09.2017
Сообщений: 11,404
|
|
17.08.2021, 14:49 | 39 |
Я замещаю теорию реальностью.
Нет. Это означает, что она может в каких-то случаях работать неправильно. Но в тех условиях, под которые писалась, работать будет как задумано. Не, TheCalligrapher постоянно говорит что мол "скомпилировалось по случайности", "компилятор не должен такого допускать" и другие высказывания в духе "если программа расходится со стандартом, она однозначно нерабочая, и в принципе не должна компилироваться". Так я несколько разных вариантов привел.
0
|
19409 / 10028 / 2443
Регистрация: 30.01.2014
Сообщений: 17,678
|
|
17.08.2021, 14:58 | 40 |
Ни один из них не подходит, потому что они все используются в Си. Выше было сказано:
Часть их них при этом легальны и в С++. Такого однозначного определения по которому все ваши варианты UB не было. Наверняка если сейчас начнем разбирать конкретные примеры, то, как и здесь, окажется, что все не совсем так.
0
|
17.08.2021, 14:58 | |
17.08.2021, 14:58 | |
Помогаю со студенческими работами здесь
40
Почему диапазон значений у типа float больше, чем у типа int, если они оба занимают 4 байта? Как число типа 2.88007e+018 привести в обычный int, float или просто вывести Как в один Label Вывести текст и значение переменной типа float? Переменной d присвоить первую цифру после запятой некоторой переменной x типа float Не происходит конвертация типа int в float Ошибка: "Значение типа float нельзя присвоить сущности типа int" Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |