使用C ++将四个字节转换为Integer

时间:2016-01-22 10:00:01

标签: c++

我正在尝试使用C ++将4个字节转换为整数。

这是我的代码:

int buffToInteger(char * buffer)
{
    int a = (int)(buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3]);
    return a;
}

上述代码几乎适用于所有情况,例如: 当我的缓冲区为:"[\x00, \x00, \x40, \x00]"时,代码将按预期返回16384

但是当缓冲区充满:"[\x00, \x00, \x3e, \xe3]"时,代码将无法正常工作并返回"ffffffe1"

有谁知道为什么会这样?

5 个答案:

答案 0 :(得分:19)

您的buffer包含已签名的字符。实际上,buffer[0] == -29在转换为int后会被转换为0xffffffe3,并依次(0x3e << 8) | 0xffffffe3 == 0xffffffe3

您需要确保将buffer个字节解释为unsigned,方法是将buffer声明为unsigned char *,或明确转换:

int a = int((unsigned char)(buffer[0]) << 24 |
            (unsigned char)(buffer[1]) << 16 |
            (unsigned char)(buffer[2]) << 8 |
            (unsigned char)(buffer[3]));

答案 1 :(得分:5)

在表达式buffer[0] << 24中,值24为int,因此在执行转换之前,buffer[0]也会转换为int

在您的系统上,char显然已签名,然后在转换为int后进行签名扩展。

答案 2 :(得分:2)

在轮班中对签名的int进行隐含的提升。 那是因为char(显然)在你的平台上签名(常见的东西)和&lt;&lt;隐含地促进整数。事实上,这一切都不会起作用,因为&lt;&lt; 8(及更高)会磨掉你所有的位!

如果您因使用签名字符缓冲区而陷入困境,这将为您提供所需内容:

#include <iostream>
#include <iomanip>

int buffToInteger(char * buffer)
{
    int a = static_cast<int>(static_cast<unsigned char>(buffer[0]) << 24 |
        static_cast<unsigned char>(buffer[1]) << 16 | 
        static_cast<unsigned char>(buffer[2]) << 8 | 
        static_cast<unsigned char>(buffer[3]));
    return a;
}

int main(void) {
    char buff[4]={0x0,0x0,0x3e,static_cast<char>(0xe3)};
    int a=buffToInteger(buff);

    std::cout<<std::hex<<a<<std::endl;

    // your code goes here
    return 0;
}

注意有符号值的位移。促销活动不仅可以添加字节,还可以转换价值。

例如,这里的问题是您不能直接使用static_cast<unsigned int>(buffer[1])(等),因为它会将signed char值转换为signed int,然后将该值重新解释为unsigned。

如果有人问我所有隐含的数字转换都很糟糕。没有任何计划应该有这么多,他们会成为一件苦差事。从C继承的C ++中的软性会导致各种各样的问题远远超过它们的价值。 它在C ++中更糟糕,因为它们使已经令人困惑的重载规则更加令人困惑。

答案 3 :(得分:2)

unsigned byte buffer[4];
int a;
a = *(int*)&buffer;

答案 4 :(得分:0)

我认为也可以通过使用memcpy来完成:

int buffToInteger(char* buffer)
{
    int a;
    memcpy( &a, buffer, sizeof( int ) );
    return a;
}

这比原始文章中提到的示例要快得多,因为它仅按“原样”对待所有字节,并且无需执行任何操作,例如移位等。 它也不会引起任何未签名的问题。