我需要将以下格式的4字节数据转换为原始int值。我不能将下面的int赋值更改为4字节。
int main() {
//code
int num = 1000;
char a[4];
a[0] = ( char )(num>>24) ;
a[1] = ( char )(num>>16) ;
a[2] = ( char )(num>>8) ;
a[3] = ( char )num ;
printf("Original number is:%d\n", (a[0] << 24 | a[1] << 16 | a[2] << 8 | a[3] ) );
return 0;
}我原以为输出是1000,但输出是768。如何从上面的字节数组中恢复原始数字?这是一个不可否认的问题吗?
发布于 2020-03-05 22:26:34
a[0] = ( char )(num>>24) ;
在本例中,这是“好的”。然而,在num为负的情况下,结果是实现定义的(C 2018 6.5.7 5)。
在其余分配给a[1]、a[2]和a[3]的赋值中,可能超出char范围的值将自动转换为char。如果对char进行签名,则这些转换的结果是实现定义的或发出信号的(6.3.1.3 3)。因此,这是一个我们必须解决的问题,下面。
首先,对于num = 1000,假设−24存储在a[3]中。这就是我们通过使用1000的低8位,并将它们放在一个8位2位的补充char中得到的结果,这很可能是您的实现所使用的。然后,我们有a[0] = 0,a[1] = 0,a[2] = 3和a[3] =−24。
现在让我们考虑一下a[0] << 24 | a[1] << 16 | a[2] << 8 | a[3]。
a[0] << 24和a[1] << 16都得到0。a[2] << 8是3 << 8,它产生768,或300十六进制。a[3]是−24。虽然a[3]是一个char,但在表达式(6.3.1.1 2)中使用时,它被提升为int。假设您的C实现使用了两个补码,−24的二进制是1111111111111111111111111111101000,或者是十六进制的−。
当我们按位OR 300和ffffffe8,结果是ffffffe8,在32位2的补码int中,是−24。
解决这一问题的最简单方法是将char a[4];更改为unsigned char a[4];。这避免了任何负的char值。
但是,要使代码完全适用于int的任何值(假设它是4个字节和两个补码),我们需要做一些其他更改:
unsigned char a[4];
/* Convert the signed num to unsigned before shifting.
Shifts of unsigned values are better defined than shifts
of signed values.
*/
a[0] = (unsigned) num >> 24;
a[1] = (unsigned) num >> 16;
a[2] = (unsigned) num >> 8;
a[3] = (unsigned) num;
/* The cast in the last assignment is not really needed since
we are assigning to an unsigned char, and it will be converted
as desired, but we keep it for uniformity.
*/
// Reconstruct the value using all unsigned values.
unsigned u = (unsigned) a[0] << 24 | (unsigned) a[1] << 16 | (unsigned) a[2] << 8 | a[3];
/* Copy the bits into an int. (Include <string.h> to get memcpy.)
Note: It is easy to go from signed to unsigned because the C standard
completely defines that conversion. For unsigned to signed, the
conversion is not completely defined, so we have to use some indirect
method to get the bits into an int.
*/
int i;
memcpy(&i, &u, sizeof i);
printf("Original number: %d.\n", i);我们需要使用一个unsigned值来重建位,因为C的shift运算符没有很好地定义有符号值,特别是当我们想要将位转换为符号位时。一旦我们有了unsigned对象中的位,就可以将它们复制到int中。
https://stackoverflow.com/questions/60554495
复制相似问题