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

时间:2018-07-11 10:37:43

标签: c++

我有一个长指针值,它指向一个20字节的标头结构,后跟一个更大的数组。 Dec(57987104)=十六进制(0374D020)。所有值都存储为little endian。交换时为1400,则为0014,十进制为20。

enter image description here

这里的问题是如何获取第一个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);
}

如何从长指针中提取小端无符号的短符号?

2 个答案:

答案 0 :(得分: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>导出的大小整数类型。

编辑:

刚刚意识到您的数据实际上是小端的:)

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));
}

答案 1 :(得分:-1)

假设您用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];
这就是我误会我的想法