C:将无符号字符数组转换为有符号整数(反之亦然)

C:将无符号字符数组转换为有符号整数(反之亦然),c,arrays,C,Arrays,我试图将无符号字符数组缓冲区转换为有符号整数(反之亦然) 下面是演示代码: int main(int argv, char* argc[]) { int original = 1054; unsigned int i = 1054; unsigned char c[4]; int num; memcpy(c, (char*)&i, sizeof(int)); //num = *(int*) c;

我试图将无符号字符数组缓冲区转换为有符号整数(反之亦然)

下面是演示代码:

int main(int argv, char* argc[])
{
    int original = 1054;
    unsigned int i = 1054;
    unsigned char c[4];
    int num;

    memcpy(c, (char*)&i, sizeof(int));

    //num  = *(int*) c;                          // method 1 get
    memcpy((char *)&num, c, sizeof(int));        // method 2 get
    printf("%d\n", num);

    return 0;
}
1)从unsigned char[]到int应该使用哪种方法?

方法1获取还是方法2获取? (或任何建议)

2)如何将整型原始字符转换为无符号字符[]?

我需要通过只接受无符号字符[]的缓冲区发送这个整数

目前我正在做的是将int转换为unsigned int,然后再转换为char[],例如:

int g = 1054;
unsigned char buf[4];
unsigned int n;
n = g;
memcpy(buf, (char*)&n, sizeof(int));
虽然它工作正常,但我不确定这是正确的方法还是安全的


另外,我正在尝试通过USB串行通信(Raspberry Pi和Arduino之间)在两台设备之间发送数据。

您可以将
int
(或
无符号int
)和
无符号字符
数组存储为
union
。这种方法被调用,并且从C99开始就按照标准对其进行完全消毒(尽管这在早期是常见的做法)。假设
sizeof(int)==4

#include <stdio.h>

union device_buffer {
    int i;
    unsigned char c[4];
};

int main(int argv, char* argc[])
{
    int original = 1054;

    union device_buffer db;
    db.i = original;

    for (int i = 0; i < 4; i++) {
        printf("c[i] = 0x%x\n", db.c[i]);
    }
}
#包括
联合装置缓冲区{
int i;
无符号字符c[4];
};
int main(int argv,char*argc[])
{
int原始值=1054;
联合装置缓冲数据库;
db.i=原件;
对于(int i=0;i<4;i++){
printf(“c[i]=0x%x\n”,db.c[i]);
}
}

请注意,数组中的值是由于endianness而存储的。

下面的方法将工作,而不管机器上的endianness如何(假设
sizeof(int)==4
):

上面的代码以小尾端的方式将整数转换为字节数组。这里还有更多的信息

有关反向操作,请参见答案


使用
memcpy
的方法可能会在不同的计算机上产生不同的结果。因为
memcpy
会将源地址中的任何内容复制到目标地址,并且取决于计算机是小端还是大端,在起始源地址可能有一个LSB或MSB。

不确定它是否安全,但有一件事可以让它不那么不安全,那就是说
unsigned char buf[sizeof(int)]
而不是
无符号字符buf[4]
。如果字符数组未正确对齐
num=*(int*)c
请不要这样做,
c
不需要为
int
正确对齐。谢谢所有建议!要坚持memcpy方法
*(int*)c
也违反了严格的别名规则,不要这样做我在stackoverflow上看到memcpy和union可能会产生不同的结果!这是真的吗?union和struct之间有什么区别?谢谢!请注意,通过联合的类型双关仍然是C++中的UB;普遍安全的方法仍然是
memcpy
@DoeJoe:char是我的打字错误,现在它是正确的。对于第二个问题,memcpy和union的结果应该完全相同,因为您在同一台计算机上运行代码。@DoeJoe:除非您存储的值超出了
int
的范围,否则这无关紧要。无论如何,我改为unsigned,因为你的问题就是这样。如果int小于4个字符,那么这就是ub:
db.I=original
未初始化剩余的字符。尽管所有这些
&0xff
实际上都不是必需的(但它们可能会添加一些清晰的内容)。使用您的代码,它会产生另一个endianness结果(c数组是我当前使用并正在工作的数组,字节数组是您建议的数组):c[I]=0x2d c[I]=0x0 c[I]=0x0 c[i]=0x0字节[i]=0x0字节[i]=0x0字节[i]=0x0字节[i]=0x0字节[i]=0x2d@DoeJoe你可以试试小恩迪安的方法-我会的modify@Somebody由于相似的原因,联合会在不同的机器上给出不同的结果memcpy@DoeJoe这并不是说小恩迪安能工作,而大恩迪安不能。这就是方法。我提到的方法,如果您使用该方法以小端方式编码整数,并在不同的机器上应用类似的反向操作(从字节数组中恢复整数,假设字节以小端方式),您将得到相同的结果。同样的方法也适用于任何机器,即使您以big-endian方式转换整数。现在,也许你的设备需要整数的长度,这是另一回事。你可能想对endianness做更多的研究。
unsigned char bytes[4];
unsigned int n = 45;

bytes[3] = (n >> 24) & 0xFF;
bytes[2] = (n >> 16) & 0xFF;
bytes[3] = (n >> 8) & 0xFF;
bytes[0] = n & 0xFF;