Форум программистов, компьютерный форум, киберфорум
C++
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.87/47: Рейтинг темы: голосов - 47, средняя оценка - 4.87
1 / 1 / 0
Регистрация: 10.06.2013
Сообщений: 153
1

Интерпретация переменной типа int как float

16.08.2021, 20:49. Показов 8679. Ответов 53
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
C++
1
int a = 1143816535
Как мне получилось 693,0209351 во float?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
16.08.2021, 20:49
Ответы с готовыми решениями:

Это значение 5.9875e17 может быть сохранено в переменной, типа: int bool long short float?
#include <iostream> using namespace std; int main() { float a = 5.9875e17; cout<<a; }...

Как присвоить значение одного из элементов массива типа char переменной типа int?
С++ начал буквально только что так что буду благодарен за терпение и понимание ) Сразу оговорюсь...

ОШИБКА [Error] cannot convert 'int*' to 'float*' for argument '1' to 'void Syma(float*,int*,int)
Какая то проблема с указателями,незнаю,не хочет щитать суму парних чисел в второй...

Как сохранить float в переменной типа char?
Всем здрасьте. Как можно записать float в char ? И как потом float вытащить из char, если он...

53
Эксперт С++
8972 / 4318 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
16.08.2021, 21:53 21
Author24 — интернет-сервис помощи студентам
Цитата Сообщение от Verevkin Посмотреть сообщение
int a = 1143816535;
float *ptr = &a;
float f = *ptr;
Код
error: cannot convert ‘int*’ to ‘float*’ in initialization
Цитата Сообщение от Verevkin Посмотреть сообщение
float f = *(float*)&a;
UB

Код
warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
Цитата Сообщение от Verevkin Посмотреть сообщение
U.a = 1143816535;
это вообще не скомпилируется.
наверное, ты имел ввиду:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
 
union U
{
  int32_t a;
  float f;
};
 
int main()
{
    U v;
    v.a = 1143816535;
    std::cout << v.f;
}
несмотря на то, что на практике,
трюк с объединением прокатывает на всех топовых компиляторах,
тем не менее, формально, такой код содержит UB.

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

Добавлено через 6 минут
Цитата Сообщение от Verevkin Посмотреть сообщение
Я, например, сразу понял, что хотел автор - интерпретировать 4 байт
в старых версиях с++ такое было невозможно провернуть не налетев на UB

в новом с++ можно воспользоваться std::launder
и это - единственный легальный способ реинтерпретировать "теплое" как "мягкое"

C++
1
2
3
4
5
6
7
8
#include <iostream>
 
int main()
{
    int a = 1143816535;
    float& f = *std::launder(reinterpret_cast<float*>(&a));
    std::cout << f << '\n';
}
2
Злостный нарушитель
9542 / 5172 / 1182
Регистрация: 12.03.2015
Сообщений: 24,414
16.08.2021, 21:55 22
Цитата Сообщение от hoggy Посмотреть сообщение
в старых версиях с++ такое было невозможно провернуть не налетев на UB
А как это можно смоделировать?
0
Модератор
Эксперт функциональных языков программированияЭксперт Python
37329 / 20761 / 4275
Регистрация: 12.02.2012
Сообщений: 34,167
Записей в блоге: 14
16.08.2021, 21:58 23
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Оба варианта - грубейше неправильные.
- странно, что "грубейше неправильные" варианты тем не менее транслируются и успешно исполняются... Невольно возникает вопрос: почему язык не запрещает подобные конструкции? Или конкретнее - почему их пропускает компилятор?
0
Эксперт С++
8972 / 4318 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
16.08.2021, 22:00 24
Цитата Сообщение от Verevkin Посмотреть сообщение
А как это можно смоделировать?
ну вот например

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
 
int foo( float *f, int *i ) { 
    *i = 1;               
    *f = 0.f;            
   return *i;
}
 
int main() {
    int x = 0;
    
    std::cout << x << "\n";   // Expect 0
    x = foo(reinterpret_cast<float*>(&x), &x);
    std::cout << x << "\n";   // Expect 0?
}
output:
Код
0
1
0
Вездепух
Эксперт CЭксперт С++
12783 / 6662 / 1793
Регистрация: 18.10.2014
Сообщений: 16,849
16.08.2021, 22:06 25
Цитата Сообщение от Catstail Посмотреть сообщение
странно, что "грубейше неправильные" варианты тем не менее транслируются и успешно исполняются...
Странно, что в форуме по С++ (пусть даже "для начинающих"), приводят в качестве "аргумента" такой детский лепет, как "эти варианты транслируются и успешно исполняются", как будто не понимают, что в С и С++ ваше "транслируются и успешно исполняются" не значит вообще ничего. Неужели за весь период существования этого форума даже завсегдатаи не смогли усвоить таких элементаранызх понятий, как неопределнное поведение?

В очередной раз спрошу с нескрываемым удивлением: вот это вот "транслируются и успешно исполняются" - это такой троллинг? Или здесь все действиельно настольоко запущено?
0
Злостный нарушитель
9542 / 5172 / 1182
Регистрация: 12.03.2015
Сообщений: 24,414
16.08.2021, 22:06 26
Цитата Сообщение от hoggy Посмотреть сообщение
ну вот например
Да я не про это. Я про "создать такие условия, чтобы мой код выдал неверный результат".
0
Вездепух
Эксперт CЭксперт С++
12783 / 6662 / 1793
Регистрация: 18.10.2014
Сообщений: 16,849
16.08.2021, 22:07 27
Цитата Сообщение от Catstail Посмотреть сообщение
Невольно возникает вопрос: почему язык не запрещает подобные конструкции? Или конкретнее - почему их пропускает компилятор?
Рука-лицо... "Почему компилятор разрешает мне писать неправильные программы"?
0
Модератор
Эксперт функциональных языков программированияЭксперт Python
37329 / 20761 / 4275
Регистрация: 12.02.2012
Сообщений: 34,167
Записей в блоге: 14
16.08.2021, 22:12 28
TheCalligrapher, нет это не троллинг. Это вопрос к системе типов. Что стоило просто запретить подобные преобразования - и не было бы проблем. Если Вы мне объясните это (и я пойму), то буду благодарен... Когда меня убеждают - я соглашаюсь.

А вот когда мне заявляют менторским тоном "Это так и никак иначе", а на вопрос "Почему?" отвечают "Потому", то я упираюсь. Мне кажется, это мое право.
2
Вездепух
Эксперт CЭксперт С++
12783 / 6662 / 1793
Регистрация: 18.10.2014
Сообщений: 16,849
16.08.2021, 22:17 29
Цитата Сообщение от hoggy Посмотреть сообщение
в новом с++ можно воспользоваться std::launder
Нет, нельзя. Никакого отношения к прямой реинтерпретации std::launder не имеет. Требование std::launder<T> - по целевому адресу располагается именно объект типа T.

Добавлено через 4 минуты
Цитата Сообщение от Catstail Посмотреть сообщение
нет это не троллинг. Это вопрос к системе типов. Что стоило просто запретить подобные преобразования - и не было бы проблем.
Невозможно на стадии компиляции "запретить преобразования", когда их корректность в общем случае зависит от факторов времени выполнения.

Цитата Сообщение от Catstail Посмотреть сообщение
Если Вы мне объясните это (и я пойму), то буду благодарен... Когда меня убеждают - я соглашаюсь.
А вот когда мне заявляют менторским тоном "Это так и никак иначе", а на вопрос "Почему?" отвечают "Потому", то я упираюсь.
Тема 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
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Нет, нельзя. Никакого отношения к прямой реинтерпретации std::launder не имеет. Требование std::launder<T> - по целевому адресу располагается именно объект типа T.
да, действительно.
0
Модератор
Эксперт функциональных языков программированияЭксперт Python
37329 / 20761 / 4275
Регистрация: 12.02.2012
Сообщений: 34,167
Записей в блоге: 14
17.08.2021, 07:02 31
TheCalligrapher, понял. Спасибо.
0
4017 / 2563 / 430
Регистрация: 09.09.2017
Сообщений: 11,404
17.08.2021, 10:12 32
Цитата Сообщение от hoggy Посмотреть сообщение
формально, такой код содержит UB.
лично я не стал бы ставить на такой код свою карьеру.
Насколько я слышал, такой трюк использовался для быстрого вычисления обратного корня.
Цитата Сообщение от Verevkin Посмотреть сообщение
А как это можно смоделировать?
Сложно. Возможно, сломается на big/little endian, возможно с другим размером байта (стандарт дозволяет!) или еще при каких-то экзотических условиях.
Цитата Сообщение от Catstail Посмотреть сообщение
странно, что "грубейше неправильные" варианты тем не менее транслируются и успешно исполняются... Невольно возникает вопрос: почему язык не запрещает подобные конструкции? Или конкретнее - почему их пропускает компилятор?
Потому что С (а следом и С++) заточены под ручную оптимизацию. Если программист знает, что делает - не надо ему мешать.
Цитата Сообщение от hoggy Посмотреть сообщение
ну вот например
Чуть упрощу ваш код:
C
1
2
3
4
5
6
7
8
9
10
int func(int *arg){
  *arg = 2;
  return 3;
}
 
int main(){
  int x = 0;
  x = func(&x);
  printf("%i\n", x);
}
Ожидаемо x=3. К чему нужны извращения с reinterpret_cast и что вы вообще хотели продемонстрировать?
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
как будто не понимают, что в С и С++ ваше "транслируются и успешно исполняются" не значит вообще ничего
Да все прекрасно понимают, что ваше "не значит ничего" не значит ничего. Если код транслируется и выполняется, то он транслируется и выполняется. И если он написан грамотно, то даже при наличии UB он продолжит транслироваться и выполняться как задумано, и им прекрасно можно пользоваться. Высокоуровневый ассемблер на то и высокоуровневый ассемблер чтобы давать возможность привязаться к особенностям конкретной платформы.

Добавлено через 7 минут
Цитата Сообщение от Catstail Посмотреть сообщение
Что стоило просто запретить подобные преобразования - и не было бы проблем.
Так проблем и нет. Собственно, это одно из применений union'ов - интерпретация одной и той же кучки битов как разные типы. Один пример я уже описал - вычисление обратного корня. Второй - разбиение переменной на байты:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
#include <stdint.h>
 
typedef union{
  uint32_t val_32;
  struct{
    uint8_t b1;
    uint8_t b2;
    uint8_t b3;
    uint8_t b4;
  };
}Bytes4;
 
int main(){
  Bytes4 val;
  val.val_32 = 0x12345678;
  printf("%.2X %.2X %.2X %.2X\n", val.b1, val.b2, val.b3, val.b4);
}
С некоторой натяжкой сюда же можно отнести систему событий в различных оконных системах вроде SDL или curses. Идентификатор события читается из наиболее общей структуры, и уже потом по нему идет каст к нужной. Но по определению TheCalligrapher, это все равно UB. Но, как обычно, крики "неправильный код! Не компилируется!" никого не волнуют. Код работает, люди им пользуются.
3
Злостный нарушитель
9542 / 5172 / 1182
Регистрация: 12.03.2015
Сообщений: 24,414
17.08.2021, 10:17 33
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Сложно. Возможно, сломается на big/little endian
А чего, 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
Цитата Сообщение от Verevkin Посмотреть сообщение
Если у int сменить порядок байтов, то у float он тоже должен измениться, разве нет?
Не знаю. Но допускаю и такую возможность. Все-таки к байтам int'а можно обращаться по отдельности скажем для сложения, то float имеет смысл только как неделимая 32-битная сущность.
0
19409 / 10028 / 2443
Регистрация: 30.01.2014
Сообщений: 17,678
17.08.2021, 11:53 35
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
К чему нужны извращения с reinterpret_cast и что вы вообще хотели продемонстрировать?
Это код из этой статьи, там же все объяснено, зачем и чего код демонстрирует.

Добавлено через 19 минут
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
И если он написан грамотно, то даже при наличии UB он продолжит транслироваться и выполняться как задумано, и им прекрасно можно пользоваться. Высокоуровневый ассемблер на то и высокоуровневый ассемблер чтобы давать возможность привязаться к особенностям конкретной платформы.
У вас тут смешаны понятия implementation-defined behavior, unspecified-behavior и undefined-behavior.
Вся аргументация про высокоуровневый ассемблер и грамотный код справедлива только для первых двух понятий, но никак не для последнего.

Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Идентификатор события читается из наиболее общей структуры, и уже потом по нему идет каст к нужной. Но по определению TheCalligrapher, это все равно UB.
По его определению этот как раз не UB, потому что в этом случае по идентификатору мы точно понимаем что было записано при отправке события, и каст делаем именно к тому типу, который был записан. Т.е. тут нет type punning, и нет UB. Это применение union как раз является правильным во всех смыслах.
Кроме того, как было уже сказано, в языке С разрешен type punning через union, в языке С это не UB.
Кроме того, разработчики компиляторов С++ прекрасно знают, что трюк с реинтерпретацией через union очень популярен и в коде на С++, поэтому не реализуют никаких помех для его выполнения. Но это не делает код корректным, так же как не делает правильным забег через дорогу на красный свет, не смотря на то, что миллионы человек могут похвастаться, что с ними во время этого ничего не случилось.

Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
крики
Не понятно почему аргументация к спецификации языка является "криками", ничего нового он не сказал, это все известно еще со времен C++98.
Можно или нельзя в конкретном проекте плевать на несоответствие кода спецификации (в части корректности) - это вообще отдельный вопрос, который тут не обсуждался даже.
0
Эксперт С++
8972 / 4318 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
17.08.2021, 12:28 36
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Чуть упрощу ваш код:
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
К чему нужны извращения с reinterpret_cast и что вы вообще хотели продемонстрировать?
а зачем ты его начал чуть упрощать,
если ты даже не понял, зачем он был нужен?
0
4017 / 2563 / 430
Регистрация: 09.09.2017
Сообщений: 11,404
17.08.2021, 13:38 37
Цитата Сообщение от DrOffset Посмотреть сообщение
У вас тут смешаны понятия implementation-defined behavior, unspecified-behavior и undefined-behavior.
Так ведь они и в реальности не слишком далеки друг от друга.
Цитата Сообщение от DrOffset Посмотреть сообщение
По его определению этот как раз не UB, потому что в этом случае по идентификатору мы точно понимаем что было записано при отправке события
Приблизительно оно выглядит так:
C
1
2
3
4
5
6
7
8
9
10
11
struct Event{
  uint32_t type;
  uint8_t reserved[?];
};
struct Event_moude{
  uint32_t type;
  uint16_t x, y, wheel;
  uint8_t button[3];
  uint8_t reserved[?];
};
и т.д.
То есть обработчик событий ОС заполняет структуру Event_mouse, а юзерский код читает сначала Event, полагаясь на то, что поле type будет расположено в одном и том же месте. Налицо запись в одну версию union'а, а чтение из другой.
Цитата Сообщение от DrOffset Посмотреть сообщение
Но это не делает код корректным, так же как не делает правильным забег через дорогу на красный свет, не смотря на то, что миллионы человек могут похвастаться, что с ними во время этого ничего не случилось.
Разумеется, делает. Да, в некоторых случаях возникнет проблема с переносимостью, но если разработчик сознательно использует подобные трюки, он ей сознательно жертвует ради скорости или читаемости. Равно как и переход дороги на красный свет, когда совершенно точно известно, что она перекрыта и движения на ней нет.
Цитата Сообщение от DrOffset Посмотреть сообщение
Не понятно почему аргументация к спецификации языка является "криками"
Спецификация языка не говорит, что программа, содержащая UB, некорректна или тем более не должна компилироваться. Учитывая особенность С/С++, обойтись вот совсем без UB вряд ли возможно. Либо код станет совершенно нечитаемым и неэффективным. Уж слишком много они позволяют разработчикам компилятора.
Ну а агрессивное навязывание своих фантазий, противоречащих реальному миру, и выглядит как бесполезные крики. Как полагались люди на безопасность переполнения знаковых чисел, так и будут. Как кастовали что угодно к чему угодно, так и будут. Как считали байт восьмибитным, так и будут считать. Не нравится - пусть идет в другие языки, где подобные вольности не дозволяются.
Цитата Сообщение от hoggy Посмотреть сообщение
а зачем ты его начал чуть упрощать,
если ты даже не понял, зачем он был нужен?
Ну так разверните свою мысль. Что именно иллюстрирует ваш код и как он относится к вопросу Verevkin'а о касте int -> float?
0
19409 / 10028 / 2443
Регистрация: 30.01.2014
Сообщений: 17,678
17.08.2021, 13:49 38
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Разумеется, делает. Да, в некоторых случаях возникнет проблема с переносимостью, но если разработчик сознательно использует подобные трюки, он ей сознательно жертвует ради скорости или читаемости. Равно как и переход дороги на красный свет, когда совершенно точно известно, что она перекрыта и движения на ней нет.
Не замещайте общее частным.

Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Спецификация языка не говорит, что программа, содержащая UB, некорректна
Не говорит, но и гарантий корректности тоже не дает. Это прямо и означает, что программа в неопределенном состоянии.

Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
тем более не должна компилироваться.
Про "компилироваться" там выше было совсем в другом контексте сказано. Не в том смысле, что не компилируется из-за UB. Там не компилировалось из-за неявного каста между несовместимыми типами.

Добавлено через 1 минуту
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Налицо запись в одну версию union'а, а чтение из другой.
Для такого случая, когда есть layout-compatible, и С++ тоже разрешает это делать.
Речь же не об этих случаях.
0
4017 / 2563 / 430
Регистрация: 09.09.2017
Сообщений: 11,404
17.08.2021, 14:49 39
Цитата Сообщение от DrOffset Посмотреть сообщение
Не замещайте общее частным.
Я замещаю теорию реальностью.
Цитата Сообщение от DrOffset Посмотреть сообщение
Не говорит, но и гарантий корректности тоже не дает. Это прямо и означает, что программа в неопределенном состоянии.
Нет. Это означает, что она может в каких-то случаях работать неправильно. Но в тех условиях, под которые писалась, работать будет как задумано.
Цитата Сообщение от DrOffset Посмотреть сообщение
Про "компилироваться" там выше было совсем в другом контексте сказано. Не в том смысле, что не компилируется из-за UB.
Не, TheCalligrapher постоянно говорит что мол "скомпилировалось по случайности", "компилятор не должен такого допускать" и другие высказывания в духе "если программа расходится со стандартом, она однозначно нерабочая, и в принципе не должна компилироваться".
Цитата Сообщение от DrOffset Посмотреть сообщение
Речь же не об этих случаях.
Так я несколько разных вариантов привел.
0
19409 / 10028 / 2443
Регистрация: 30.01.2014
Сообщений: 17,678
17.08.2021, 14:58 40
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Так я несколько разных вариантов привел.
Ни один из них не подходит, потому что они все используются в Си. Выше было сказано:
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
такое допустимо только в С
Часть их них при этом легальны и в С++. Такого однозначного определения по которому все ваши варианты UB
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Но по определению TheCalligrapher, это все равно UB.
не было.

Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
другие высказывания в духе "если программа расходится со стандартом, она однозначно нерабочая, и в принципе не должна компилироваться".
Наверняка если сейчас начнем разбирать конкретные примеры, то, как и здесь, окажется, что все не совсем так.
0
17.08.2021, 14:58
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
17.08.2021, 14:58
Помогаю со студенческими работами здесь

Почему диапазон значений у типа float больше, чем у типа int, если они оба занимают 4 байта?
Почему диапазон значений флоат больше чем у инта, если они оба занимают 4 байта? Вроде слышал...

Как число типа 2.88007e+018 привести в обычный int, float или просто вывести
Тестирующая система говорит &quot;Неправильный формат вывода&quot;. Программа считает числа фиббоначи, по...

Как в один Label Вывести текст и значение переменной типа float?
Пример Картошка: 21 кг Как это вывести в один Label?

Переменной d присвоить первую цифру после запятой некоторой переменной x типа float
Нужно целой переменной d присвоить первую цыфру после комы некоторой переменной x типа float ...

Не происходит конвертация типа int в float
int r = 130; r = (float)r/255; r равен 0. Почему не произошла конвертация типа?

Ошибка: "Значение типа float нельзя присвоить сущности типа int"
При компиляции в Visual C++ получается такая ошибка: &quot;Значение типа float нельзя присвоить сущности...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru