我需要能够将数值发送到远程套接字服务器,因此我需要将可能的数字编码为字节。
数字最多为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 :(得分:3)
您需要明确投射type
以避免警告:
*p++ = (unsigned char) type;
您希望首先使用最高有效字节对数字进行编码,但是您向错误的方向移动。循环应该是:
for (int i = sizeof(uint32_t) - 1; i >= 0; --i)
*p++ = (unsigned char) ((number >> (i * 8)) & 0xFF);
看起来不错。
答案 1 :(得分: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;
答案 2 :(得分:0)
你的代码是合理的(虽然我使用uint8_t,因为你没有使用字节作为“字符”,而Peter当然是正确的错字),而不像常见的替代品如
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]
甚至可以保证有效。第一种替代方案可能适用于调试版本,但越来越多的编译器可能会在优化时破坏它,而第二种编译器往往在实践中几乎无处不在,但是语言标准明确标记为坏事。 / p>
答案 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;
}
这使得调用者可以更容易地将多个片段连接成一个大的二进制数据包,并跟踪已使用/需要的缓冲区大小。