C++ 如何在具有8位成员的队列中前进,并将耦合合并为16位值
我有一个指向一个数组的指针,它包含四对8位值,比如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; 是否可以在一个班轮中完成此操作 为什么只有一艘班轮? 真的没有什么特别的原因
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;