[英]How do I extract little-endian unsigned short from long pointer?
I have a long pointer value that points to a 20 byte header structure followed by a larger array. 我有一个长指针值,它指向一个20字节的标头结构,后跟一个更大的数组。 Dec(57987104)=Hex(0374D020). Dec(57987104)=十六进制(0374D020)。 All the values are stored little endian. 所有值都存储为little endian。 1400 when swapped is 0014 which in decimal is 20. 交换时的1400为0014,十进制为20。
The question here is how do I get the first value which is a 2 byte unsigned short. 这里的问题是如何获取第一个2字节无符号短的值。 I have a C++ dll to convert this for me. 我有一个C ++ dll为我转换。 I'm running Windows 10. 我正在运行Windows 10。
GetCellData_API unsigned short __stdcall getUnsignedShort(unsigned long ptr)
{
unsigned long *p = &ptr;
unsigned short ret = *p;
return ret;
}
But when I call this from VBA using Debug.Print getUnsignedShort(57987104)
I get 30008 when it should be 20. 但是,当我使用Debug.Print getUnsignedShort(57987104)
从VBA调用此函数时,应得到30008(应为20)。
I might need to do an endian swap but I'm not sure how to incorporate this from CodeGuru: How do I convert between big-endian and little-endian values? 我可能需要进行字节序交换,但是我不确定如何从CodeGuru中合并它:如何在大字节序和小字节序值之间转换?
inline void endian_swap(unsigned short& x)
{
x = (x >> 8) |
(x << 8);
}
How do I extract little endian unsigned short from long pointer? 如何从长指针中提取小端无符号的short?
I think I'd be inclined to write your interface function in terms of a general template function that describes the operation: 我想我倾向于用描述操作的通用模板函数来编写您的接口函数:
#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));
}
As you can see from the demo on godbolt , the compiler does all the hard work for you. 如您在Godbolt上的演示中所见 ,编译器为您完成了所有艰苦的工作。
Note that since we know the size of the data, I have used the sized integer types exported from <cstdint>
in case this code needs to be ported to another platform. 请注意,由于我们知道数据的大小,因此在需要将此代码移植到另一个平台的情况下,我使用了从<cstdint>
导出的大小整数类型。
EDIT: 编辑:
Just realised that your data is actually 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));
}
Lets say youre pointing with pulong pulong[6] you are pointing 6 sixth member of the table 假设您用pulong指向pulong [6]您指向的是表格的第六个成员
unsigned short psh*; unsigned char puchar* unsigend char ptable[4]; ZeroMemory(ptable,4); puchar[3]=((char *)( &pulong[6]))[0]; puchar[2]=((char *)( &pulong[6]))[1]; puchar[1]=((char *)( &pulong[6]))[2]; puchar[0]=((char *)( &pulong[6]))[3]; psh=(unsigned short *) puchar; //first one psh[0]; //second one psh[1];
THis was what was in my mind while mistaking me 这就是我误会我的想法
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.