将Char数组转换为Long in C错误

时间:2018-05-12 08:37:55

标签: c arrays char converter

我尝试将unsigned long int转换为char 但我收到了一些错误

buffalo

,输出

int main(void)
{
    unsigned char pdest[4];
    unsigned long l=0xFFFFFFFF;
    pdest[0] = l         & 0xFF;
    pdest[1] = (l >>  8) & 0xFF;
    pdest[2] = (l >> 16) & 0xFF;
    pdest[3] = (l >> 24) & 0xFF;

    unsigned long int l1=0;
    l1 |= (pdest[0]);
    l1 |= (pdest[1] << 8);
    l1 |= (pdest[2] << 16);
    l1 |= (pdest[3] << 24);

    printf ("%lu",l1);
}

不是4294967295?

如何做到正确?

7 个答案:

答案 0 :(得分:0)

阅读本文: https://en.wikipedia.org/wiki/C_data_types

  

...长无符号整数类型。能够包含至少 [0,   4,294,967,295]范围;

答案 1 :(得分:0)

您应该将最后4行写为:

l1 |= ((unsigned long) pdest[0]);
l1 |= (((unsigned long) pdest[1]) << 8);
l1 |= (((unsigned long) pdest[2]) << 16);
l1 |= (((unsigned long) pdest[3]) << 24);

因为你应该在移位之前将字节转换为unsigned long。

答案 2 :(得分:0)

pdest [3]&lt;&lt; 24的类型为signed int。

将您的代码更改为

unsigned long int l1=0;
l1 |= (pdest[0]);
l1 |= (pdest[1] << 8); 
l1 |= (pdest[2] << 16);
l1 |= ((unsigned int)pdest[3] << 24);

答案 3 :(得分:0)

问题在于char的转移。您必须在转换为超过8位的char之前强制转换为unsigned。此外,char的标志将对结果进行进一步的改动。

尝试

unsigned long int l1=0;
l1 |= ((unsigned long)pdest[0]);
l1 |= ((unsigned long)pdest[1] << 8); 
l1 |= ((unsigned long)pdest[2] << 16); 
l1 |= ((unsigned long)pdest[3] << 24); 

注意使用强制转换强制编译器在发生转换之前将char转换为unsigned。

答案 4 :(得分:0)

你的无符号长整数不必是4个字节。

#include <stdio.h>
#include <stdint.h>

int main(void) {
    int index;
    unsigned char pdest[sizeof(unsigned long)];
    unsigned long l=0xFFFFFFFFUL;

    for(index = 0; index < sizeof(unsigned long); index++)
    {
        pdest[index] = l & 0xff;
        l >>= 8;
    }

    unsigned long l1=0;
    for(index = 0; index < sizeof(unsigned long); index++)
    {
        l1 |= (unsigned long)pdest[index] << (8 * index);

    }

    printf ("%lx\n",l1);
}

答案 5 :(得分:0)

首先,要命名一个32位宽的类型,请使用uint32_t,而不是unsigned long intunsigned long int在64位* nix(通常称为LP64)中通常为64位宽,而在Windows(LLP64)中它们是32位。

无论如何,问题在于整数促销。转换级别小于intunsigned int的算术运算的操作数将转换为intunsigned int,无论其范围如何。由于所有unsigned char代表signed int s,pdest[3]转换为signed intpdest[3] << 24的结果也属signed int类型!现在,如果它具有最高有效位设置,则该位移位到整数的符号位,并且行为符合C标准 undefined

然而,海湾合作委员会已为此案定义了行为;在那里,结果只是一个带有2的补码表示的负整数;因此(unsigned char)0xFF << 24的结果是(int)-16777216。现在,对于|操作,需要将其提升为其他操作数的等级,即unsigned。无符号转换就好像通过重复加或减一个多于最大值(即重复加或减2)直到该值适合该值的范围。由于您的平台上unsigned long为64位,因此此转换的结果为2 ^ 64 - 16777216或18446744073692774400,它与先前步骤中的位进行了“或”运算。

如何解决?很容易,就在轮班之前,将每个移位的数字转换为uint32_t。在PRIu32宏的帮助下打印:

#include <inttypes.h>

...

uint32_t l1=0;
l1 |= (uint32_t)pdest[0];
l1 |= (uint32_t)pdest[1] << 8;
l1 |= (uint32_t)pdest[2] << 16;
l1 |= (uint32_t)pdest[3] << 24;
printf ("%" PRIu32, l1);

答案 6 :(得分:0)

你的代码的问题是unsigned char到int的隐式类型转换,然后是带有符号或操作的带符号扩展的unsigned long,每行的相应值如下所示

l1 |= (pdest[0]);   //dec = 255 hex = 0xFF
l1 |= (pdest[1] << 8);   //dec = 65535 hex = 0xFFFF
l1 |= (pdest[2] << 16);  //dec = 16777215 hex =0xFFFFFF
l1 |= (pdest[3] << 24);  //here is the problem

在最后一行pdest[3] << 24 = 0xFF000000中由于隐式转换为int而等同于-16777216。对于按位或操作,它再次转换为无符号长整数,其中有符号扩展名在l1 |= (pdest[3] << 24)中发生,相当于0x0000000000FFFFFF | 0xFFFFFFFFFF000000

许多人建议您可以使用显式类型转换,或者您可以使用下面的代码段

l1 = (l1 << 0) | pdest[3];
l1 = (l1 << 8) | pdest[2];
l1 = (l1 << 8) | pdest[1];
l1 = (l1 << 8) | pdest[0];

我希望它能解决你的问题,并为这么大的输出提供理由。