Dalam ceramahnya yang baru-baru ini "Tipe punning in C ++ modern" Timur Doumler mengatakan bahwa std::bit_cast
tidak dapat digunakan untuk menggigit sebuah float
ke dalam unsigned char[4]
karena array gaya-C tidak dapat dikembalikan dari suatu fungsi. Kita harus menggunakan std::memcpy
atau menunggu sampai C ++ 23 (atau lebih baru) ketika sesuatu seperti reinterpret_cast<unsigned char*>(&f)[i]
akan menjadi terdefinisi dengan baik.
Di C ++ 20, bisakah kita menggunakan std::array
with std::bit_cast
,
float f = /* some value */;
auto bits = std::bit_cast<std::array<unsigned char, sizeof(float)>>(f);
bukannya array C-style untuk mendapatkan byte dari float
?
sumber
struct X { unsigned char elems[5]; };
memenuhi aturan yang Anda kutip. Ini tentu saja dapat diinisialisasi daftar hingga 4 elemen. Ini juga dapat diinisialisasi daftar dengan 5 elemen. Saya tidak berpikir ada pelaksana perpustakaan standar yang cukup membenci orang untuk benar-benar melakukan ini, tapi saya pikir itu sesuai secara teknis.elems[5]
. Dan pada saat itu saya tidak bisa melihat bagaimana Anda bisa berakhir dengan agregat di manasizeof(array<char, sizeof(T)>) != sizeof(T)
?struct X { unsigned char c1, c2, c3, c4; };
ataustruct X { unsigned char elems[4]; };
- jadi sementara karakter harus merupakan elemen dari agregat tersebut, ini memungkinkan mereka untuk menjadi elemen agregat langsung atau elemen sub-agregat tunggal.P -> Q
tidak menyiratkan apa pun tentang kasus di mana!P
array
itu sendiri tidak akan memiliki bantalan. Implementasi itu mungkin tidak memiliki padding (dan implementasi apa pun yang harus dianggap disfungsional), tetapi tidak ada jaminan bahwaarray
itu sendiri tidak akan.Jawaban yang diterima salah karena gagal mempertimbangkan masalah pelurusan dan bantalan.
Per [array] / 1-3 :
Standar tidak benar-benar harus
std::array
memiliki tepat satu anggota data publik tipeT[N]
, jadi secara teori dimungkinkan bahwasizeof(To) != sizeof(From)
atauis_trivially_copyable_v<To>
.Saya akan terkejut jika ini tidak berhasil dalam prakteknya.
sumber
Iya.
Menurut kertas yang menggambarkan perilaku
std::bit_cast
, dan implementasi yang diusulkan sejauh kedua jenis memiliki ukuran yang sama dan dapat ditiru, para pemeran harus berhasil.Implementasi yang disederhanakan
std::bit_cast
harus berupa:Karena float (4 byte) dan array
unsigned char
dengansize_of(float)
hormat semua menegaskan, yang mendasarinyastd::memcpy
akan dilakukan. Oleh karena itu, setiap elemen dalam array yang dihasilkan akan menjadi satu byte berturut-turut dari float.Untuk membuktikan perilaku ini, saya menulis contoh kecil di Compiler Explorer yang dapat Anda coba di sini: https://godbolt.org/z/4G21zS . Float 5.0 disimpan dengan benar sebagai array byte (
Ox40a00000
) yang sesuai dengan representasi heksadesimal dari nomor float di Big Endian .sumber
std::array
dijamin tidak memiliki bit padding, dll.?auto bits = reinterpret_cast<std::array<unsigned char, sizeof(float)>&>(f)
dan mendapatkan hasil yang persis sama. Apakah itu membuktikan sesuatu?std::array
memenuhi persyaratan ContiguiosContainer (sejak C ++ 17) .std::vector
juga memenuhi kriteria yang sama dan jelas tidak dapat digunakan di sini. Apakah ada sesuatu yang mengharuskanstd::array
memegang elemen di dalam kelas (dalam bidang), mencegahnya menjadi pointer sederhana ke array batin? (seperti dalam vektor, yang juga memiliki ukuran, array mana yang tidak perlu ada dalam bidang)std::array
secara efektif membutuhkannya untuk menyimpan elemen di dalamnya, tapi saya khawatir tentang masalah tata letak.