将int转换为4字节char数组(C)

Jac*_*son 67 c

嘿,我正在寻找将用户输入的int转换为4个字节,我将其分配给字符数组.如何才能做到这一点?

例:

将用户输入175转换为

00000000 00000000 00000000 10101111


到目前为止所有答案的问题,转换255应该导致0 0 0 ff尽管它打印出来:0 0 0 ffffffff

unsigned int value = 255;   

buffer[0] = (value >> 24) & 0xFF;
buffer[1] = (value >> 16) & 0xFF;
buffer[2] = (value >> 8) & 0xFF;
buffer[3] = value & 0xFF;

union {
    unsigned int integer;
    unsigned char byte[4];
} temp32bitint;

temp32bitint.integer = value;
buffer[8] = temp32bitint.byte[3];
buffer[9] = temp32bitint.byte[2];
buffer[10] = temp32bitint.byte[1];
buffer[11] = temp32bitint.byte[0];
Run Code Online (Sandbox Code Playgroud)

两者都导致0 0 0 ffffffff而不是0 0 0 ff

另一个例子是175,因为输入打印出来就像0, 0, 0, ffffffaf它应该的那样0, 0, 0, af

caf*_*caf 137

这样做的便携式方法(确保您0x00 0x00 0x00 0xaf到处都是)是使用班次:

unsigned char bytes[4];
unsigned long n = 175;

bytes[0] = (n >> 24) & 0xFF;
bytes[1] = (n >> 16) & 0xFF;
bytes[2] = (n >> 8) & 0xFF;
bytes[3] = n & 0xFF;
Run Code Online (Sandbox Code Playgroud)

使用联合的方法memcpy()将在不同的机器上获得不同的结果.


您遇到的问题是打印而不是转换.我认为你使用的是char而不是unsigned char,并且你使用这样的行来打印它:

printf("%x %x %x %x\n", bytes[0], bytes[1], bytes[2], bytes[3]);
Run Code Online (Sandbox Code Playgroud)

当任何类型比int传递的更窄时printf,它们将被提升为int(或者unsigned int,如果int不能保存原始类型的所有值).如果char在您的平台上签名,则0xff可能不适合该类型的范围,而是将其设置为-1(其0xff在2s补码机器上具有表示).

-1被提升为a int,并且在您的机器上具有表示0xffffffff形式int,这就是您所看到的.

您的解决方案是实际使用unsigned char,或者unsigned char在printf声明中转换为:

printf("%x %x %x %x\n", (unsigned char)bytes[0],
                        (unsigned char)bytes[1],
                        (unsigned char)bytes[2],
                        (unsigned char)bytes[3]);
Run Code Online (Sandbox Code Playgroud)

  • @rem:虽然不常见,但`char`被允许宽于8位(某些DSP编程环境表现出这种情况),因此掩码只是确保在这种情况下正确的事情发生.对于常见情况,它无论如何都会被优化. (4认同)
  • @jacobnlsn:这是打印方式的问题,请参阅更新. (2认同)
  • ZerOne:“&”是按位与,当且仅当两个操作数中的相应位都为 1 时,给出的结果是每个位都为 1。然后“a & 0xFF”给出的结果是最低 8 位与最低 8 位相同‘a’中的位,其余位全部为零。 (2认同)

Bla*_*ace 14

您想要解决32位int的各个字节吗?一种可能的方法是结合:

union
{
    unsigned int integer;
    unsigned char byte[4];
} foo;

int main()
{
    foo.integer = 123456789;
    printf("%u %u %u %u\n", foo.byte[3], foo.byte[2], foo.byte[1], foo.byte[0]);
}
Run Code Online (Sandbox Code Playgroud)

注意:更正了printf以反映无符号值.

  • 我写的是uint32_t而不是int,只是为了不用担心32位和64位机器. (5认同)

vil*_*apx 6

在您的问题中,您声明要将用户输入175转换 00000000 00000000 00000000 10101111为大端字节顺序,也称为网络字节顺序.

从您给出的"175"示例中建议的,将无符号整数转换为大端无符号字符数组的大多数可移植方法是使用C htonl()函数(<arpa/inet.h>在Linux系统的头文件中定义)将unsigned int转换为大端字节顺序,然后使用memcpy()(在<string.h>C 的头文件中<cstring>为C++定义)将字节复制到char(或unsigned char)数组中.

该htonl()函数接受一个无符号的32位整数作为参数(相反htons(),它采用无符号的16位整数)并将其从主机字节顺序转换为网络字节顺序(因此首字母缩写,Host TO Network Long,与主机TO网络短路htons),将结果作为无符号的32位整数返回.此系列函数的目的是确保所有网络通信都以大端字节顺序发生,以便所有计算机可以通过套接字相互通信而不会出现字节顺序问题.(顺便说一句,对于大端机器,htonl(),htons(),ntohl()和ntohs()功能通常编译成只是一个"无操作",因为字节不需要围绕翻转他们是从一个插座,因为他们送过来或者接收之前'已经按正确的字节顺序)

这是代码:

#include <stdio.h>
#include <arpa/inet.h>
#include <string.h>

int main() {
    unsigned int number = 175;

    unsigned int number2 = htonl(number);
    char numberStr[4];
    memcpy(numberStr, &number2, 4);

    printf("%x %x %x %x\n", numberStr[0], numberStr[1], numberStr[2], numberStr[3]);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

请注意,正如caf所说,您必须使用printf的格式说明符将字符打印为无符号字符%x.

上面的代码打印0 0 0 af在我的机器上(x86_64机器,它使用小端字节排序),它是175的十六进制.