我有一个长指针值,指向一个 20 字节的头结构,后跟一个更大的数组。十二月(57987104)=十六进制(0374D020)。所有的值都以小端存储。交换时的 1400 为 0014,十进制为 20。
这里的问题是如何获得第一个值,它是一个 2 字节的无符号短整型。我有一个 C++ dll 来为我转换它。我正在运行 Windows 10。
GetCellData_API unsigned short __stdcall getUnsignedShort(unsigned long ptr)
{
unsigned long *p = &ptr;
unsigned short ret = *p;
return ret;
}
但是当我使用 VBA 调用Debug.Print getUnsignedShort(57987104)
它时,我得到 30008,而它应该是 20。
我可能需要进行字节序交换,但我不确定如何从CodeGuru合并此内容:如何在大端和小端值之间进行转换?
inline void endian_swap(unsigned short& x)
{
x = (x >> 8) |
(x << 8);
}
如何从长指针中提取 little endian unsigned short?
我想我倾向于根据描述操作的通用模板函数来编写您的接口函数:
#include <utility>
#include <cstdint>
// Code for the general case
// you'll be amazed at the compiler's optimiser
template<class Integral>
auto extract_be(const std::uint8_t* buffer)
{
using accumulator_type = std::make_unsigned_t<Integral>;
auto acc = accumulator_type(0);
auto count = sizeof(Integral);
while(count--)
{
acc |= accumulator_type(*buffer++) << (8 * count);
}
return Integral(acc);
}
GetCellData_API unsigned short __stdcall getUnsignedShort(std::uintptr_t ptr)
{
return extract_be<std::uint16_t>(reinterpret_cast<const std::uint8_t*>(ptr));
}
正如您在 Godbolt 上的演示中看到的那样,编译器为您完成了所有繁重的工作。
请注意,由于我们知道数据的大小,因此我使用了从中导出的大小整数类型<cstdint>
,以防需要将此代码移植到另一个平台。
编辑:
刚刚意识到您的数据实际上是 LITTLE Endian :)
template<class Integral>
auto extract_le(const std::uint8_t* buffer)
{
using accumulator_type = std::make_unsigned_t<Integral>;
auto acc = accumulator_type(0);
constexpr auto size = sizeof(Integral);
for(std::size_t count = 0 ; count < size ; ++count)
{
acc |= accumulator_type(*buffer++) << (8 * count);
}
return Integral(acc);
}
GetCellData_API unsigned short __stdcall getUnsignedShort(std::uintptr_t ptr)
{
return extract_le<std::uint16_t>(reinterpret_cast<const std::uint8_t*>(ptr));
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句