Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Преобразование double в __int64 
:(
    Опции темы
J0ker
Дата 18.12.2008, 18:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 986
Регистрация: 17.9.2008

Репутация: 4
Всего: 14



Цитата(Earnest @ 18.12.2008,  14:21)
Нет, в данном контексте это использование по назначению - т.е. в вычислениях (или в присваивании).
И потом, никто не говорит, что UB - это когда программа падает. Это просто значит, что результат получится неизвестно какой.
Скажем, целая -1, если ее таким образом преобразовать в double становится Not-a-number. И что там в вычислениях получится -  хто знает. 
Например, если сравнивать NAN с любым числом, то результат стабилен (не помню уже true или false), независимо от того, какое число и какое сравнение. С другой стороны - это не раз наблюдаемое мною поведение наверняка является свойством конкретного компилятора или может даже параметров компиляции (release-debug).

А писать-читать в память ты можешь что угодно - была бы память. Это ведь по сути ничем не отличается от memcpy, как предложил Void, только запись яснее (на мой взгляд).  Reinterpret_cast биты не портит... Т.е. если ты запихиваешь, скажем float в LPARAM, чтобы послать сообщение, а потом его оттуда извлекаешь обратной операцией, то все совершенно нормально и легально.

вот тут вы совершенно НЕ правы
связано это не с возможностью/невозможностью конкретного преобразования типа, а с оптимизацией
дело в том, что компилятор зачастую не в состоянии отследить алиасинг, что может приводить при оптимизации к сайдэффектам
например следующий код:
Код

long x=5;
*(short *)&x = 10;
printf("%d", x);

без оптимизации может выдавать "10", а с оптимизацией - "5"
если такое случится, и вы посмотрите на оптимизированный ассемблерный код, то сможете заметить странную вещь - printf либо вызывается с константой - совершенно не взирая на реальное значение переменной, либо присвоение происходит после вызова printf
Обсуждение подобного эффекта тут:
http://www.rsdn.ru/Forum/message/2630988.flat.1.aspx

ЗЫЖ да, если что - вышеприведенный пример ессесна не портируем на биг-ендиан будет явная лажа  smile 

Это сообщение отредактировал(а) J0ker - 18.12.2008, 18:52


--------------------
user posted image
PM MAIL   Вверх
J0ker
Дата 18.12.2008, 19:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 986
Регистрация: 17.9.2008

Репутация: 4
Всего: 14



да, вот еще
5.17/8
Цитата

If the value being stored in an object is accessed from another object that overlaps in any way the storage of
the first object, then the overlap shall be exact and the two objects shall have the same type, otherwise the
behavior is undefined
.



--------------------
user posted image
PM MAIL   Вверх
Earnest
Дата 19.12.2008, 09:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



Речь идет совсем не о том, чтобы преобразовать типы и спать спокойно, а том, чтобы сделать это ВРЕМЕННО.
Если ты собираешься запихнуть double в int64, а потом пользоваться этим int'ом, то да, это не безопасно. Но если int64 использовать как временное хранилище для битов дабла, то ничего с твоим даблом не случится. А твой пример с printf вообще из другой оперы.


--------------------
...
PM   Вверх
J0ker
Дата 19.12.2008, 18:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 986
Регистрация: 17.9.2008

Репутация: 4
Всего: 14



ну не знаю... надо анрила спросить... что-то мне кажется формально это подподает под UB


--------------------
user posted image
PM MAIL   Вверх
GoldFinch
Дата 19.12.2008, 20:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



****


Профиль
Группа: Завсегдатай
Сообщений: 2141
Регистрация: 30.11.2008

Репутация: 15
Всего: 26



где это уже обсуждалось, толко речь шла о float
так вот в переменную размером N байт можно запихнуть любую другую переменную N байт и ничего с ней не случиться.
PM MAIL ICQ   Вверх
UnrealMan
Дата 19.12.2008, 20:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 722
Регистрация: 30.3.2006

Репутация: 27
Всего: 32



Начнём с того, что в стандарте C++ нету встроенного типа __int64 smile
Далее, т.к. стандарт не обязывает double иметь не более строгие требования к выравниванию, чем __int64, то результат reinterpret_cast-а из __int64 * в double * - unspecified.

Цитата(Earnest @  18.12.2008,  14:21 Найти цитируемый пост)
А писать-читать в память ты можешь что угодно - была бы память. Это ведь по сути ничем не отличается от memcpy

Отличается. На некоторых архитектурах несоблюдение выравнивания приводит к аппаратному исключению. Так что memcpy надёжнее.

Это сообщение отредактировал(а) UnrealMan - 19.12.2008, 21:17
PM MAIL   Вверх
J0ker
Дата 19.12.2008, 21:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 986
Регистрация: 17.9.2008

Репутация: 4
Всего: 14



UnrealMan, а конкретно под 3.10/15 и 5.17/8 это подпадает?


--------------------
user posted image
PM MAIL   Вверх
UnrealMan
Дата 19.12.2008, 23:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 722
Регистрация: 30.3.2006

Репутация: 27
Всего: 32



Цитата(J0ker @  19.12.2008,  21:51 Найти цитируемый пост)
а конкретно под 3.10/15 и 5.17/8 это подпадает? 

Под 3.10/15 подпадает, под 5.17/8 - нет.
PM MAIL   Вверх
Earnest
Дата 22.12.2008, 14:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



Цитата(UnrealMan @  19.12.2008,  21:49 Найти цитируемый пост)
Далее, т.к. стандарт не обязывает double иметь не более строгие требования к выравниванию, чем __int64, то результат reinterpret_cast-а из __int64 * в double * - unspecified.

Возможно, в случае с выравниванием и да. Но если я заведу union как предлагала, с обоими этими типами - согласись, все должно быть ок. Хотя, конечно, не факт, что тогда размер юниона будет равен размеру double. Но это уже поддается контролю при сборке.
Кроме того, в жизни такого не встречала (разницы в выравнивании). 
Конечно, на какой-то отдельно взятой и не очень распростаненной платформе - наверное, возможно. Но человек, который на ней програмирует, видимо, должен это знать. А код, который пишется под широко распросраненные платформы вряд ли кто-то расчитывает перенести на какие-то специальные, не прикладывая специальных усилий.
Так что все эти рассуждения очень похожи на теоретическую опастность попасть под кирпич, прогуливаясь по улице.


--------------------
...
PM   Вверх
UnrealMan
Дата 22.12.2008, 15:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 722
Регистрация: 30.3.2006

Репутация: 27
Всего: 32



Цитата(Earnest @  22.12.2008,  14:22 Найти цитируемый пост)
Но если я заведу union как предлагала, с обоими этими типами - согласись, все должно быть ок. 

По стандарту нет (см. 3.10/15), но с практической точки зрения, скорее всего, да (если размер double не превышает 64 бит). Другое дело, что непонятно, зачем это нужно - переводить double в __int64 и обратно.
PM MAIL   Вверх
J0ker
Дата 22.12.2008, 23:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 986
Регистрация: 17.9.2008

Репутация: 4
Всего: 14



Цитата(UnrealMan @ 22.12.2008,  15:45)
Цитата(Earnest @  22.12.2008,  14:22 Найти цитируемый пост)
Но если я заведу union как предлагала, с обоими этими типами - согласись, все должно быть ок. 

По стандарту нет (см. 3.10/15), но с практической точки зрения, скорее всего, да (если размер double не превышает 64 бит). Другое дело, что непонятно, зачем это нужно - переводить double в __int64 и обратно.

разве это не разрешает делать это через union?:
Цитата

— an aggregate or union type that includes one of the aforementioned types among its members (including,
recursively, a member of a subaggregate or contained union),



--------------------
user posted image
PM MAIL   Вверх
UnrealMan
Дата 23.12.2008, 07:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 722
Регистрация: 30.3.2006

Репутация: 27
Всего: 32



Цитата(J0ker @  22.12.2008,  23:20 Найти цитируемый пост)
разве это не разрешает делать это через union?

Прочитай внимательно правило целиком.
PM MAIL   Вверх
Earnest
Дата 23.12.2008, 13:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



Если речь о конвертации, а выравнивание неодинаковое (или что-то еще неодинаковое), то обмен через union действительно некорректен - нет гарантии, что все биты будут общими. Корректно только само присваивание. Поскольку union должен быть выделен так, чтобы все комфортно разместились. Я имела в виду именно это.

Цитата(UnrealMan @  22.12.2008,  16:45 Найти цитируемый пост)
дело, что непонятно, зачем это нужно - переводить double в __int64 и обратно. 

Ну, скажем, чтобы передать параметр процедуре, принимающей исключительно int64. Реальный пример  (здесь 
правда речь идет o паре float\DWORD) - послать сообщение с параметром float (притом что там есть только DWORD параметры).


--------------------
...
PM   Вверх
UnrealMan
Дата 23.12.2008, 17:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 722
Регистрация: 30.3.2006

Репутация: 27
Всего: 32



Цитата(Earnest @  23.12.2008,  13:16 Найти цитируемый пост)
Ну, скажем, чтобы передать параметр процедуре, принимающей исключительно int64. 

Ну, если процедура изначально написана через ж., и альтернативы её использованию нет, то тут всё понятно. В норме же аргументы неизвестных типов передаются через указатели void * или char *, а не запихиваются в целочисленные объекты.
PM MAIL   Вверх
GoldFinch
Дата 23.12.2008, 19:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



****


Профиль
Группа: Завсегдатай
Сообщений: 2141
Регистрация: 30.11.2008

Репутация: 15
Всего: 26



UnrealMan, а нафига создавать переменную в которой будет храниться это значение, вычислять указатель на это значение, если можно просто передать его по значению?
PM MAIL ICQ   Вверх
Страницы: (4) Все 1 [2] 3 4 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0919 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.