C++ 如何在具有8位成员的队列中前进,并将耦合合并为16位值

C++ 如何在具有8位成员的队列中前进,并将耦合合并为16位值,c++,c,bit-manipulation,C++,C,Bit Manipulation,我有一个指向一个数组的指针,它包含四对8位值,比如 MSB-lsb-MSB-lsb-MSB-lsb-MSB-lsb ^ | bufPointer 我将在此队列中前进,并用这四个8位对填充fooStruct结构的16位成员 对于第一位成员,我可以用以下两行代码来完成此操作: fooStruct.M1 = *bufPointer << 8; fooStruct.M1 |= *++bufPointer; 是否可以在一个班轮中完成此操作 为什么只有一艘班轮? 真的没有什么特别的原因

我有一个指向一个数组的指针,它包含四对8位值,比如

MSB-lsb-MSB-lsb-MSB-lsb-MSB-lsb
 ^
 |
bufPointer
我将在此队列中前进,并用这四个8位对填充
fooStruct
结构的16位成员

对于第一位成员,我可以用以下两行代码来完成此操作:

fooStruct.M1 = *bufPointer << 8;
fooStruct.M1 |= *++bufPointer;
是否可以在一个班轮中完成此操作


为什么只有一艘班轮?
真的没有什么特别的原因。学习+好奇/如果方便,将来使用。:)

为什么在一行中做这件事如此重要

无论如何,这是一种方式:

fooStruct.M1 = (bufPointer += 2, (bufPointer[-2] << 8) | bufPointer[-1]);

fooStruct.M1=(bufPointer+=2,(bufPointer[-2])当然,你可以在一行中完成。但我想问一下为什么,因为当代码被塞进更少的行时,它的可读性总是会降低。编译器不在乎你是在一行还是几行中完成它

我认为,最具可读性的一行是每次递增:

fooStruct.M1 = (*bufPointer++ << 8) | *bufPointer++;

fooStruct.M1=(*bufPointer++是的,您可以在一行程序中完成,但为了避免序列点警告,最好像这样完成:

c = (*p << 8) | *(p + 1);

因为使用C++,可以将缓冲区封装在更智能的“读取器”中。

类读取器
{
公众:
读卡器(字符*bufPointer)
:m_bufPointer(bufPointer){}
shortshortbe()
{

短结果=(m_bufPointer[0]接受答案的微小变化:

c = (p[0] << 8) | p[1];

你有没有在C之前学过Perl?;)@paddy为什么或者更好的说法!!!这只是对Perl程序员倾向于在一行中编写尽可能多的程序这一事实的嘲弄,即使它使程序无法维护…特别是如果它使程序无法维护的话!我想说,缩写和压缩代码并不总是有坏的影响,在某些情况下这是一个优点。在某些情况下,您可以通过一页和一眼看到工作块,因此可读性更高。但这种情况只是好奇,因为我无法理解,也无法克服:)
(*bufPointer++谢谢@TonyD,我通常都在我未定义的行为之上,但我没有意识到这是一个。现在我对我过去可能写过的包含这种风格的生产代码心存疑虑,我会将它添加到我的代码审查红旗列表中。我会从我的答案中删除这一部分。结果也会是0xlsb MSB而不是oxMSB lsb:)那
“+1”
而不是
“++”
应该有一个+1:)只是好奇而已。BE和LE代表什么,你打算在哪里使用LE?大端和小端。我只是用LE来说明。
fooStruct.M1 = (bufPointer[0] << 8) | bufPointer[1];
fooStruct.M2 = (bufPointer[2] << 8) | bufPointer[3];
fooStruct.M3 = (bufPointer[4] << 8) | bufPointer[5];
fooStruct.M4 = (bufPointer[6] << 8) | bufPointer[7];
bufPointer += 8;  // Only if you need to keep deserialising
c = (*p << 8) | *(p + 1);
#include <stdio.h>

#if defined(__LP64__) || defined(_LP64)
# define BUILD_64   1
#endif

#ifdef BUILD_64
# define BITS_PER_LONG 64
#else
# define BITS_PER_LONG 32
#endif

char *binpad (unsigned long n, size_t sz);

int main (void) {

    unsigned char a[] = { 65, 28, 59, 15 };
    unsigned char *p = NULL;
    unsigned char *end = a + sizeof a/sizeof *a;

    unsigned short c = 0;

    for (p = a; p < end; p += 2)
    {
        c = (*p << 8) | *(p + 1);

        printf ("\n *p       : %6hhu  (%s)\n", *p, binpad (*p, 16));
        printf (" *(p + 1) : %6hhu  (%s)\n", *(p + 1), binpad (*(p + 1), 16));
        printf ("\n c        : %6hu  (%s)\n", c, binpad (c, 16));
    }

    return 0;
}

char *binpad (unsigned long n, size_t sz)
{
    static char s[BITS_PER_LONG + 1] = {0};
    char *p = s + BITS_PER_LONG;
    register size_t i;

    for (i = 0; i < sz; i++)
        *(--p) = (n>>i & 1) ? '1' : '0';

    return p;
}
$ ./bin/uchar2short

 *p       :     65  (0000000001000001)
 *(p + 1) :     28  (0000000000011100)

 c        :  16668  (0100000100011100)

 *p       :     59  (0000000000111011)
 *(p + 1) :     15  (0000000000001111)

 c        :  15119  (0011101100001111)
class Reader
{
public:
    Reader(char* bufPointer)
        : m_bufPointer(bufPointer) {}

    short shortBE()
    {
        short result = (m_bufPointer[0] << 8) | m_bufPointer[1];
        m_bufPointer += 2;
        return result;
    }

    short shortLE()
    {
        short result = (m_bufPointer[1] << 8) | m_bufPointer[0];
        m_bufPointer += 2;
        return result;
    }

    // etc...
};


FooStruct DeserializeFooStruct(char* bufPointer)
{
   Reader rd(bufPointer);

   FooStruct fooStruct;
   fooStruct.M1 = rd.shortBE();
   fooStruct.M2 = rd.shortBE();
   // and so on
   return fooStruct;
}
c = (p[0] << 8) | p[1];
c = *(short*)p;