简体   繁体   English

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

[英]Converting an int into a 4 byte char array (C)

Hey, I'm looking to convert a int that is inputed by the user into 4 bytes, that I am assigning to a character array. 嘿,我正在寻找将用户输入的int转换为4个字节,我将其分配给字符数组。 How can this be done? 如何才能做到这一点?

Example: 例:

Convert a user inputs of 175 to 将用户输入175转换为

00000000 00000000 00000000 10101111


Issue with all of the answers so far, converting 255 should result in 0 0 0 ff although it prints out as: 0 0 0 ffffffff 到目前为止所有答案的问题,转换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];

both result in 0 0 0 ffffffff instead of 0 0 0 ff 两者都导致0 0 0 ffffffff而不是0 0 0 ff

Just another example is 175 as the input prints out as 0, 0, 0, ffffffaf when it should just be 0, 0, 0, af 另一个例子是175,因为输入打印为0, 0, 0, ffffffaf ,它应该只是0, 0, 0, af

The portable way to do this (ensuring that you get 0x00 0x00 0x00 0xaf everywhere) is to use shifts: 这样做的可移植方式(确保你到处都得到0x00 0x00 0x00 0xaf )是使用shift:

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;

The methods using unions and memcpy() will get a different result on different machines. 使用联合和memcpy()将在不同的机器上获得不同的结果。


The issue you are having is with the printing rather than the conversion. 您遇到的问题是打印而不是转换。 I presume you are using char rather than unsigned char , and you are using a line like this to print it: 我假设您使用的是char而不是unsigned char ,并且您使用这样的行来打印它:

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

When any types narrower than int are passed to printf , they are promoted to int (or unsigned int , if int cannot hold all the values of the original type). 当任何比int更窄的类型传递给printf ,它们将被提升为int (或unsigned int ,如果int不能保存原始类型的所有值)。 If char is signed on your platform, then 0xff likely does not fit into the range of that type, and it is being set to -1 instead (which has the representation 0xff on a 2s-complement machine). 如果在您的平台上签名char ,则0xff可能不适合该类型的范围,并且它被设置为-1(在2s补码机器上具有表示0xff )。

-1 is promoted to an int , and has the representation 0xffffffff as an int on your machine, and that is what you see. -1被提升为int ,并且在您的机器上具有表示0xffffffff作为int ,这就是您所看到的。

Your solution is to either actually use unsigned char , or else cast to unsigned char in the printf statement: 您的解决方案是实际使用unsigned char ,或者在printf语句中printfunsigned char

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

Do you want to address the individual bytes of a 32-bit int? 您想要解决32位int的各个字节吗? One possible method is a union: 一种可能的方法是结合:

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]);
}

Note: corrected the printf to reflect unsigned values. 注意:更正了printf以反映无符号值。

In your question, you stated that you want to convert a user input of 175 to 00000000 00000000 00000000 10101111 , which is big endian byte ordering, also known as network byte order . 在您的问题中,您声明要将用户输入175转换为00000000 00000000 00000000 10101111 ,这是大端字节排序,也称为网络字节顺序

A mostly portable way to convert your unsigned integer to a big endian unsigned char array, as you suggested from that "175" example you gave, would be to use C's htonl() function (defined in the header <arpa/inet.h> on Linux systems) to convert your unsigned int to big endian byte order, then use memcpy() (defined in the header <string.h> for C, <cstring> for C++) to copy the bytes into your char (or unsigned char) array. 从你给出的“175”示例中建议的,将无符号整数转换为大端无符号字符数组的大多数可移植方法是使用C的htonl()函数(在头文件<arpa/inet.h>定义htonl()在Linux系统上)将unsigned int转换为big endian字节顺序,然后使用memcpy() (在C的头文件<string.h>定义,C ++的<cstring> )将字节复制到char(或unsigned char) )数组。

The htonl() function takes in an unsigned 32-bit integer as an argument (in contrast to htons() , which takes in an unsigned 16-bit integer) and converts it to network byte order from the host byte order (hence the acronym, Host TO Network Long, versus Host TO Network Short for htons ), returning the result as an unsigned 32-bit integer. htonl()函数接受一个无符号的32位整数作为参数(与htons()相反,后者采用无符号的16位整数)并将其从主机字节顺序转换为网络字节顺序(因此是首字母缩略词) ,Host To Network Long,与Host TO Network Short for htons ),将结果作为无符号的32位整数返回。 The purpose of this family of functions is to ensure that all network communications occur in big endian byte order, so that all machines can communicate with each other over a socket without byte order issues. 此系列函数的目的是确保所有网络通信都以大端字节顺序发生,以便所有计算机可以通过套接字相互通信而不会出现字节顺序问题。 (As an aside, for big-endian machines, the htonl() , htons() , ntohl() and ntohs() functions are generally compiled to just be a 'no op', because the bytes do not need to be flipped around before they are sent over or received from a socket since they're already in the proper byte order) htonl() ,对于big-endian机器, htonl()htons()ntohl()ntohs()函数通常被编译为'no op',因为字节不需要翻转在它们被发送或从套接字接收之前,因为它们已经在正确的字节顺序中)

Here's the code: 这是代码:

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

Note that, as caf said, you have to print the characters as unsigned characters using printf's %x format specifier. 请注意,正如caf所说,您必须使用printf的%x格式说明符将字符打印为无符号字符。

The above code prints 0 0 0 af on my machine (an x86_64 machine, which uses little endian byte ordering), which is hex for 175. 上面的代码在我的机器上打印0 0 0 af (x86_64机器,它使用小端字节排序),这是175的十六进制。

You can try: 你可以试试:

void CopyInt(int value, char* buffer) {
  memcpy(buffer, (void*)value, sizeof(int));
}

为什么在C ++中你需要一个中间强制转换为void *因为cpp不允许在指针之间进行直接转换,所以你需要使用reinterpret_cast或者cast to void *。

int a = 1;
char * c = (char*)(&a); //In C++ should be intermediate cst to void*

The issue with the conversion (the reason it's giving you a ffffff at the end) is because your hex integer (that you are using the & binary operator with) is interpreted as being signed. 转换的问题(它最后给你一个ffffff的原因)是因为你的十六进制整数(你正在使用&二元运算符)被解释为被签名。 Cast it to an unsigned integer, and you'll be fine. 将它转换为无符号整数,你会没事的。

An int is equivalent to uint32_t and char to uint8_t . int等效于uint32_tchar等于uint8_t

I'll show how I resolved client-server communication, sending the actual time (4 bytes, formatted in Unix epoch) in a 1-bit array, and then re-built it in the other side. 我将展示如何解决客户端 - 服务器通信,在1位数组中发送实际时间(4个字节,在Unix纪元中格式化),然后在另一侧重新构建它。 (Note: the protocol was to send 1024 bytes) (注意:协议是发送1024字节)

  • Client side 客户端

     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); 
  • Server side 服务器端

     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); 

Hope it helps. 希望能帮助到你。

The problem is arising as unsigned char is a 4 byte number not a 1 byte number as many think, so change it to 问题出现了,因为unsigned char是一个4字节的数字,而不是许多人认为的1字节数字,因此将其更改为

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

and cast while printing, to prevent promoting to 'int' (which C does by default) 并在打印时进行转换,以防止提升为'int'(默认情况下C表示)

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

You can simply use memcpy as follows: 你可以简单地使用memcpy如下:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM