如何从长指针中提取 little-endian unsigned short?
Posted
技术标签:
【中文标题】如何从长指针中提取 little-endian unsigned short?【英文标题】:How do I extract little-endian unsigned short from long pointer? 【发布时间】:2018-07-11 10:37:43 【问题描述】:我有一个长指针值,它指向一个 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;
但是当我使用 Debug.Print getUnsignedShort(57987104)
从 VBA 调用它时,我得到 30008,而它应该是 20。
我可能需要进行字节序交换,但我不确定如何从 CodeGuru: How do I convert between big-endian and little-endian values? 合并它
inline void endian_swap(unsigned short& x)
x = (x >> 8) |
(x << 8);
如何从长指针中提取 little endian unsigned short?
【问题讨论】:
第二个无符号短值恰好为零。 【参考方案1】:我想我会倾向于用描述操作的通用模板函数来编写你的接口函数:
#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));
正如您从demo on 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));
【讨论】:
这是否易于转换以获得标题其余部分的长值? (仍在阅读/理解/测试) @D_Bester "所有的值都是大端存储的。"我想你的意思是说“小端” 有了你的新版本,我回到了-19957。还是不行。 @D_Bester 你能在coliru.stacked-crooked.com 上发布一个 MCVE 并与我分享以演示这个问题吗? @D_Bester 因为它对我有用:coliru.stacked-crooked.com/a/2b82f5e3a7b627ca【参考方案2】:假设你用 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];
这就是我误会时的想法
【讨论】:
这不能回答我的问题。它甚至不编译。我看不到如何将指针放入您的代码中,并且它不输出任何十进制值。所以这似乎与我无关。 如果这与endian_swap
有关,那么您错过了我的问题,应该删除这个答案。我什至不知道endian_swap
是否与我的问题相关。我认为不是。
感谢您的宝贵时间。以上是关于如何从长指针中提取 little-endian unsigned short?的主要内容,如果未能解决你的问题,请参考以下文章