2011-09-10 58 views
0

我需要能够将数值发送到远程套接字服务器,因此我需要将可能的数字编码为字节。如何将数值编码为字节

这些数字最多为64位,即最多需要8个字节。第一个字节是类型,它始终是255以下的数字,因此适合1个字节。

例如,如果数字是8并且类型是32位无符号整数,那么类型将是7,它将被复制到第一个(最左边的)字节,然后接下来的4个字节将用实际数字(在这种情况下为8)。

所以以字节为单位:

byte1: 7 
byte2: 0 
byte3: 0 
byte4: 0 
byte5: 8 

我希望这是决策意识。

执行此编码的代码看起来是否合理?

int type = 7; 
uint32_t number = 8; 

unsigned char* msg7 = (unsigned char*)malloc(5); 
unsigned char* p = msg7; 

*p++ = type; 

for (int i = sizeof(uint32_t) - 1; i >= 0; --i) 
    *p++ = number & 0xFF << (i * 8); 
+0

[不要在C中输入'malloc'的结果](http://stackoverflow.com/q/605845/995714) –

回答

3

你要明确投type避免警告:

*p++ = (unsigned char) type; 

你想要加入首先对最重要的字节进行编号,但是您的方向错误。回路应该是:

for (int i = sizeof(uint32_t) - 1; i >= 0; --i) 
    *p++ = (unsigned char) ((number >> (i * 8)) & 0xFF); 

否则看起来不错。

+0

您还修复了另一个您没有提到的问题:他的代码正在移动0xff掩码,而不是“数字”,因此4个字节中的3个始终设置为零。不过,它固定在你的手中。 – Dmitri

+0

正如在这种情况下,每当我不确定优先级时,我都认为没有其他人会确定其中的任何一个,并且我使用圆括号将其清除。 –

0

你的意思是?

for (int i = sizeof(uint32_t) - 1; i >= 0; --i) 
    *p++ = (number >> (i * 8)) & 0xFF; 

另一种选择可能是做

// this would work on Big endian systems, e.g. sparc 
struct unsignedMsg { 
    unsigned char type; 
    uint32_t value; 
} 

unsignedMsg msg; 
msg.type = 7; 
msg.value = number; 
unsigned char *p = (unsigned char *) &msg; 

unsigned char* p = 
p[0] = 7; 
*((uint32_t *) &(p[1])) = number; 
+0

'value'的字节表示是否取决于平台的字节顺序? –

+0

@Tom,是的,我稍后添加了评论。只要平台匹配,它不会是一个问题。 x86/x64系统通常是小端,这是要求的。 –

+1

OP在最后一个字节中有8个 - 是不是那个大端? –

0

你的代码是合理的(虽然我会使用uint8_t,因为你没有使用字节为“人物”,彼得当然是正确的WRT错字),而不像像

uint32_t number = 8; 
uint8_t* p = (uint8_t *) &number; 
的常见方案

union { 
    uint32_t number; 
    uint8_t bytes[4]; 
} val; 
val.number = 8; 
// access val.bytes[0] .. val.bytes[3] 

即使是保证工作。第一种方法可能在调试版本中工作,但是越来越多的编译器在优化时可能会破坏它,而第二种方法往往可以在任何地方实际工作,但被语言标准明确标记为坏事™。

0

我会下降循环,使用“来电者分配”的界面,像

int convert_32 (unsigned char *target, size_t size, uint32_t val) 
{ 
if (size < 5) return -1; 

target[0] = 7; 
target[1] = (val >> 24) & 0xff; 
target[2] = (val >> 16) & 0xff; 
target[3] = (val >> 8) & 0xff; 
target[4] = (val) & 0xff; 

return 5; 
} 

这使得它更容易为呼叫者多个片段连接成一个大的二进制包,并跟踪中的使用/所需的缓冲区大小。

+0

关于调用者分配的好处。我会用这个想法。 –

相关问题