c语言 - 在内存中可移植地写入二进制补码整数的算法



假设我有以下内容:

int32 a = ...; // value of variable irrelevant; can be negative
unsigned char *buf = malloc(4); /* assuming octet bytes, this is just big 
                          enough to hold an int32 */

是否有一种有效且可移植的算法以可移植的方式将a的二补大端表示写入4字节缓冲区buf?也就是说,无论我们运行的机器如何在内部表示整数,我如何才能有效地将a的两个补码表示写入缓冲区?

这是一个C问题,因此您可以根据C标准来确定您的答案是否符合可移植性要求。

是的,你当然可以便携地完成:

int32_t a = ...;
uint32_t b = a;
unsigned char *buf = malloc(sizeof a);
uint32_t mask = (1U << CHAR_BIT) - 1;  // one-byte mask
for (int i = 0; i < sizeof a; i++)
{
    int shift = CHAR_BIT * (sizeof a - i - 1); // downshift amount to put next
                                               // byte in low bits
    buf[i] = (b >> shift) & mask;  // save current byte to buffer
}

至少,我认为这是对的。我会做一个快速测试。

unsigned long tmp = a; // Converts to "twos complement"
unsigned char *buf = malloc(4);
buf[0] = tmp>>24 & 255;
buf[1] = tmp>>16 & 255;
buf[2] = tmp>>8 & 255;
buf[3] = tmp & 255;

如果假设CHAR_BIT == 8,则可以删除& 255部分。

如果我理解正确,无论int32是如何表示的,您都希望将int32的4个字节按特定顺序(例如,先低字节)存储在char缓冲区中。

让我们首先明确这些假设:sizeof(char)=8,two's compliment,sizeof(int32)=4。

不,您的代码中没有可移植的方法,因为您正试图将其转换为char而不是unsigned char。在char中存储字节是实现定义的。

但是,如果将其存储在unsigned char阵列中,则有一些可移植的方法。您可以每次将值右移8位,以在生成的数组中形成一个字节,或者使用逐位和运算符&:

// a is unsigned
1st byte = a & 0xFF
2nd byte = a>>8 & 0xFF
3rd byte = a>>16 & 0xFF
4th byte = a>>24 & 0xFF

最新更新