Почему std :: memcpy (как альтернатива наказанию типов) не вызывает неопределенного поведения? - PullRequest
3 голосов
/ 03 октября 2019

При поиске способа объединения sizeof(double) char с в double, я прочитал в нескольких постах, что использование std::memcpy было рекомендуемым способом:

char bytes[sizeof(double)];
// fill array
double d;
std::memcpy(&d, bytes, sizeof(double));

Однако,Интересно, почему дальнейшее использование d может быть определено поведением.

Если бы это был не double, а объект сложного класса, доступ к нему, безусловно, тоже не был бы определен, не так ли? Итак, почему так должно быть в случае double.

Редактировать: Чтобы прояснить мою проблему, я хочу указать свою цель: я хотел бы найти способ объединить несколькоchar s до double и далее используйте этот дубль, не вызывая неопределенного поведения. Я не ожидаю, что будет указано значение double. В любом случае, я считаю это невозможным, поскольку в стандарте ничего не говорится о размере, не говоря уже о битовой разметке double. Тем не менее, я требую d, чтобы некоторые действительные (т. Е. 'Доступные') double -значения.

Ответы [ 3 ]

3 голосов
/ 03 октября 2019

Запрещение типов запрещено, потому что сама идея над этим издевается над объектной моделью C ++. Часть памяти хранит объект, и если вы начинаете обращаться к нему, как будто он хранит какой-то другой объект, то что это вообще значит? Если вы можете просто читать из памяти как int, записывать в нее как float, а потом читать из нее как short, тогда что это вообще означает, что объект существует?

Копирование байтов между тривиально копируемыми объектами - это просто еще один способ установки значения этого объекта. Действительно, это то, что логически означает, что объект должен быть «тривиально копируемым»: что значение этого объекта определяется исключительно последовательностью байтов, составляющих его объектное представление (это не относится к сложным объектам). Но святость того, какая память принадлежит каким объектам, сохраняется. Здесь нет «вкалывания»;просто копирование данных вокруг.

2 голосов
/ 03 октября 2019

Почему наложение текста с использованием std :: memcpy не вызывает неопределенного поведения?

Поскольку язык так говорит (последний вариант):

[basic.types]

Для любого объекта (кроме потенциально перекрывающегося подобъекта) тривиально копируемого типа T, независимо от того, содержит ли объект допустимое значение типа T, лежащие в основе байты ([intro.memory]) составляющий объект может быть скопирован в массив char, unsigned char или std :: byte ([cstddef.syn]). Если содержимое этого массива копируется обратно в объект, объект должен впоследствии сохранять свое первоначальное значение.

Обратите внимание, однако, на условие этого правила. Ваш код может потенциально иметь неопределенное поведение, но нет (если это не указано в другом правиле) в случае, если скопированное значение было первоначально скопировано из другого двойного числа, или на практике, если значение могло быть скопировано из двойного числа.

Если бы это был не объект типа double, а объект сложного класса, доступ к нему точно не был бы определен, не так ли?

Зависит от того, что вы подразумеваете под сложностью. Условия, в которых это применимо, указаны в указанном правиле.

1 голос
/ 03 октября 2019

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

Вы можетеопределенно получит неопределенное поведение, если вы копируете из одного типа в байты, а затем в другой тип.

...