简体   繁体   English

如何从长指针中提取出Little-endian unsigned short?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM