是否可以将数组第一个元素的地址作为参数传递给std::bit_cast
.
#include <bit>
#include <iostream>
struct A {
int a;
int b;
int c;
int d;
int e;
void print() {
std::cout << a << ", " << b << ", " << c << ", " << d << ", " << e << std::endl;
}
};
int main() {
char arr[20]{};
// arr is filled with some data
A a = std::bit_cast<A>(arr);
a.print();
const char* arrp = arr;
// doesn't compile
A b = std::bit_cast<A>(arrp);
b.print();
}
错误
<source>: In function 'int main()':
<source>:23:27: error: no matching function for call to 'bit_cast<A>(const char*&)'
23 | A b = std::bit_cast<A>(arrp);
| ~~~~~~~~~~~~~~~~^~~~~~
In file included from <source>:1:
/opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/bit:81:5: note: candidate: 'template<class _To, class _From> constexpr _To std::bit_cast(const _From&) requires sizeof (_To) == sizeof (_From) && __is_trivially_copyable(_To) && __is_trivially_copyable(_From)'
81 | bit_cast(const _From& __from) noexcept
| ^~~~~~~~
/opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/bit:81:5: note: template argument deduction/substitution failed:
/opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/bit:81:5: note: constraints not satisfied
/opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/bit: In substitution of 'template<class _To, class _From> constexpr _To std::bit_cast(const _From&) requires sizeof (_To) == sizeof (_From) && __is_trivially_copyable(_To) && __is_trivially_copyable(_From) [with _To = A; _From = const char*]':
<source>:23:27: required from here
/opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/bit:81:5: required by the constraints of 'template<class _To, class _From> constexpr _To std::bit_cast(const _From&) requires sizeof (_To) == sizeof (_From) && __is_trivially_copyable(_To) && __is_trivially_copyable(_From)'
/opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/bit:83:27: note: the expression 'sizeof (_To) == sizeof (_From) [with _To = A; _From = const char*]' evaluated to 'false'
83 | requires (sizeof(_To) == sizeof(_From))
| ~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~
Compiler returned: 1
数组不是指针。
std::bit_cast<A>(arr);
是正确的。arr
通过引用传递,并且由于std::bit_cast
具有const From&
参数,因此From
推断为char[20]
,并且您实际上传递了const char(&)[20]
,即“对 20 个数组的引用const char
”。这与传递指针不同。另一方面,
std::bit_cast<A>(arrp);
尝试将一个指针(大小8
大概为 )进行位转换为一个A
(大小20
大概为 ),并且不能在不同大小的类型之间进行位转换。这里更好的方法是通过 进行类型双关
std::memcpy
,这种方法之所以有效,是因为A
它可以轻松复制并且具有隐式生命周期:另请参阅在 C++ 中进行类型双关的现代、正确方法是什么?
在某些情况下, An
array
可以退化为指针,但在这种情况下,它不会。相反,它仍然是一个array
,并且std::bit_cast
可以获取其地址并将其视为连续的内存块。[1]在第二种情况下,
arrp
是一个指针。当您传递arrp
给时std::bit_cast
,您传递的是一个指针,而不是一块内存。这是一个重要的区别。如果您根据 cppreference 查看建议的[cppreference]的可能实现std::bit_cast
,它表明函数参数的地址最终将被获取并作为参数传递给std::memcpy
:现在看到问题了?指针参数是意外的,因为它仍然会获取的地址
src
。您可以直接使用实现的核心,而无需进行所有检查。必须注意:您确实意识到您现在处于非常低的水平,并且很多东西都不可靠。例如,
int
可能不完全是32位。断言sizeof struct A == sizeof char arr[20]
不能保证所有实现都适用。[1]它不会衰变,因为它经过
const&