В своем недавнем выступлении « Обработка типов в современном C ++» Тимур Думлер сказал, что std::bit_cast
его нельзя использовать для float
преобразования битов в unsigned char[4]
массив, потому что массивы в стиле C не могут быть возвращены из функции. Мы должны либо использовать, std::memcpy
либо подождать до C ++ 23 (или позже), когда что-то вроде reinterpret_cast<unsigned char*>(&f)[i]
станет хорошо определенным.
В C ++ 20, мы можем использовать std::array
с std::bit_cast
,
float f = /* some value */;
auto bits = std::bit_cast<std::array<unsigned char, sizeof(float)>>(f);
вместо массива в стиле C, чтобы получить байты float
?
источник
struct X { unsigned char elems[5]; };
удовлетворяет правило, которое вы цитируете. Конечно, он может быть инициализирован до 4 элементов. Это может также быть инициализировано списком с 5 элементами. Я не думаю, что какой-либо разработчик стандартной библиотеки ненавидит людей настолько, чтобы это делать, но я думаю, что это технически соответствует.elems[5]
. И в этот момент я не вижу, как вы могли бы получить совокупность, гдеsizeof(array<char, sizeof(T)>) != sizeof(T)
?struct X { unsigned char c1, c2, c3, c4; };
илиstruct X { unsigned char elems[4]; };
- так что, хотя символы должны быть элементами этого агрегата, это позволяет им быть либо непосредственными элементами агрегата или элементы одного субагрегата.P -> Q
ничего не подразумевает случай, когда!P
array
сам по себе не будет дополнения. Реализации этого могут не иметь заполнения (и любые реализации, которые делают, должны считаться нефункциональными), но нет никакой гарантии, чтоarray
сам не будет.Принятый ответ неверен, поскольку не учитывает вопросы выравнивания и заполнения.
По [массиву] / 1-3 :
Стандарт на самом деле не требует
std::array
наличия точно одного общедоступного элемента данных типаT[N]
, поэтому теоретически это возможно, чтоsizeof(To) != sizeof(From)
илиis_trivially_copyable_v<To>
.Я буду удивлен, если на практике это не сработает.
источник
Да.
Согласно документу , описывающему поведение
std::bit_cast
и предлагаемую реализацию, поскольку оба типа имеют одинаковый размер и легко копируются, приведение должно быть успешным.Упрощенная реализация
std::bit_cast
должна выглядеть примерно так:Так как число с плавающей точкой (4 байта) и массив
unsigned char
сsize_of(float)
относительно всех тех , утверждает, лежащий в основеstd::memcpy
будет осуществляться. Следовательно, каждый элемент в результирующем массиве будет одним последовательным байтом с плавающей точкой.Чтобы доказать это поведение, я написал небольшой пример в Compiler Explorer, который вы можете попробовать здесь: https://godbolt.org/z/4G21zS . Число с плавающей запятой 5.0 должным образом хранится в виде массива bytes (
Ox40a00000
), который соответствует шестнадцатеричному представлению этого числа с плавающей запятой в Big Endian .источник
std::array
гарантированно не будет битов заполнения и т. Д.?auto bits = reinterpret_cast<std::array<unsigned char, sizeof(float)>&>(f)
и получить точно такой же вывод. Это доказывает что-нибудь?std::array
удовлетворяет требованиям ContiguiosContainer (начиная с C ++ 17) .std::vector
также удовлетворяет тем же критериям и, очевидно, не может использоваться здесь. Есть ли что-то, что требует,std::array
чтобы элементы содержались внутри класса (в поле), не давая ему быть простым указателем на внутренний массив? (как в векторе, который также имеет размер, который массив не должен иметь в поле)std::array
эффективно требует, чтобы оно содержало элементы внутри, но я беспокоюсь о проблемах макета.