首页 文章

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

提问于
浏览
57

嘿,我正在寻找将用户输入的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];

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

另一个例子是175,因为输入打印为 0, 0, 0, ffffffaf ,它应该只是 0, 0, 0, af

10 回答

  • 121

    执行此操作的可移植方式(确保您到处都是 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;
    

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


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

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

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

    -1被提升为 int ,并在您的机器上具有 0xffffffff 作为 int ,这就是您所看到的 .

    您的解决方案是实际使用 unsigned char ,或者在 printf 语句中强制转换为 unsigned char

    printf("%x %x %x %x\n", (unsigned char)bytes[0],
                            (unsigned char)bytes[1],
                            (unsigned char)bytes[2],
                            (unsigned char)bytes[3]);
    
  • 1

    您想要解决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]);
    }
    

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

  • 1

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

    如您所提供的那样,将无符号整数转换为大端无符号字符数组的大多数可移植方法是使用C的 htonl() 函数(在Linux系统的头文件 <arpa/inet.h> 中定义)将unsigned int转换为大端字节顺序,然后使用 memcpy() (在 Headers <string.h> 中定义C, <cstring> 为C)将字节复制到char(或unsigned char)数组中 .

    htonl()函数接受无符号的32位整数作为参数(与 htons() 相反,它接收无符号的16位整数)并将其从主机字节顺序转换为网络字节顺序(因此首字母缩写词,Host TO Network长,与主机TO网络短路 htons ),返回结果为无符号32位整数 . 此系列函数的目的是确保所有网络通信都以大端字节顺序发生,以便所有计算机可以通过套接字相互通信而不会出现字节顺序问题 . (顺便说一下,对于大端机器, htonl()htons()ntohl()ntohs() 函数通常被编译为'no op',因为字节不需要在从套接字发送或从套接字接收之前翻转 . 它们已经按正确的字节顺序排列了)

    这是代码:

    #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;
    }
    

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

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

  • 0

    你可以试试:

    void CopyInt(int value, char* buffer) {
      memcpy(buffer, (void*)value, sizeof(int));
    }
    
  • -1
    int a = 1;
    char * c = (char*)(&a); //In C++ should be intermediate cst to void*
    
  • 3

    你为什么需要在C中使用中间强制转换*因为cpp不允许在指针之间进行直接转换,你需要使用reinterpret_cast或强制转换为void * .

  • 15

    转换的问题(它最后给你一个ffffff的原因)是因为你的十六进制整数(你正在使用&二元运算符)被解释为被签名 . 将它转换为无符号整数,你会没事的 .

  • 6

    int 相当于 uint32_tchar 相当于 uint8_t .

    我将展示如何解决客户端 - 服务器通信,在1位数组中发送实际时间(4个字节,在Unix纪元中格式化),然后在另一侧重新构建它 . (注意:协议是发送1024字节)

    • 客户端
    uint8_t message[1024];
    uint32_t t = time(NULL);
    
    uint8_t watch[4] = { t & 255, (t >> 8) & 255, (t >> 16) & 255, (t >> 
    24) & 255 };
    
    message[0] = watch[0];
    message[1] = watch[1];
    message[2] = watch[2];
    message[3] = watch[3];
    send(socket, message, 1024, 0);
    
    • 服务器端
    uint8_t res[1024];
    uint32_t date;
    
    recv(socket, res, 1024, 0);
    
    date = res[0] + (res[1] << 8) + (res[2] << 16) + (res[3] << 24);
    
    printf("Received message from client %d sent at %d\n", socket, date);
    

    希望能帮助到你 .

  • 0

    你可以简单地使用 memcpy 作为如下:

    unsigned int value = 255;
    char bytes[4] = {0, 0, 0, 0};
    memcpy(bytes, &value, 4);
    
  • 0

    问题出现了,因为unsigned char是一个4字节的数字,而不是许多人认为的1字节数字,因此将其更改为

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

    并在打印时进行转换,以防止提升为'int'(默认情况下C表示)

    printf("%u, %u \n", (unsigned char)Buffer[0], (unsigned char)Buffer[1]);
    

相关问题