C语言 将 int 转换为 4 字节字符数组 (C)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3784263/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 06:31:03  来源:igfitidea点击:

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

c

提问by Jacob Nelson

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. How can this be done?

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

Example:

例子:

Convert a user inputs of 175 to

将用户输入 175 转换为

00000000 00000000 00000000 10101111

00000000 00000000 00000000 10101111



Issue with all of the answers so far, converting 255 should result in 0 0 0 ffalthough 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 ffffffffinstead 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, ffffffafwhen it should just be 0, 0, 0, af

另一个例子是 175 ,因为输入打印出来的0, 0, 0, ffffffaf时候应该是0, 0, 0, af

回答by caf

The portableway to do this (ensuring that you get 0x00 0x00 0x00 0xafeverywhere) is to use shifts:

做到这一点的便携方法(确保你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;

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 charrather 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 intare passed to printf, they are promoted to int(or unsigned int, if intcannot hold all the values of the original type). If charis signed on your platform, then 0xfflikely does not fit into the range of that type, and it is being set to -1 instead (which has the representation 0xffon a 2s-complement machine).

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

-1 is promoted to an int, and has the representation 0xffffffffas an inton your machine, and that is what you see.

-1 被提升为 an int,并在您的机器上表示0xffffffff为 an int,这就是您所看到的。

Your solution is to either actually use unsigned char, or else cast to unsigned charin the printfstatement:

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

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

回答by Blastfurnace

Do you want to address the individual bytes of a 32-bit int? One possible method is a union:

您想寻址 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]);
}

Note: corrected the printf to reflect unsigned values.

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

回答by villapx

In your question, you stated that you want to convert a user input of 175 to 00000000 00000000 00000000 10101111, which is big endianbyte ordering, also known as network byte order.

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

A mostlyportable 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>在 Linux 系统的头文件中定义)将您的 unsigned int 转换为大端字节序,然后使用memcpy()(在<string.h>C、<cstring>C++的头文件中定义)将字节复制到您的 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. 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()函数接受一个无符号的 32 位整数作为参数(相比之下htons(),它接受一个无符号的 16 位整数)并将其从主机字节顺序转换为网络字节顺序(因此缩写为 Host TO Network Long,与 Host TO Network 的缩写htons) 相比,将结果作为无符号 32 位整数返回。这一系列函数的目的是确保所有网络通信都以大端字节顺序进行,以便所有机器可以通过套接字相互通信,而不会出现字节顺序问题。(顺便说一句,对于大端机器htonl()htons()ntohl()ntohs()函数通常被编译为“无操作”,因为字节在发送或从套接字接收之前不需要翻转,因为它们已经处于正确的字节顺序中)

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 unsignedcharacters using printf's %xformat specifier.

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

The above code prints 0 0 0 afon my machine (an x86_64 machine, which uses little endian byte ordering), which is hex for 175.

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

回答by jbernadas

You can try:

你可以试试:

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

回答by Luiz Felipe

Why would you need an intermediate cast to void * in C++ Because cpp doesn't allow direct conversion between pointers, you need to use reinterpret_cast or casting to void* does the thing.

为什么需要在 C++ 中将中间转换为 void * 因为 cpp 不允许指针之间的直接转换,所以您需要使用 reinterpret_cast 或转换为 void* 来完成这项工作。

回答by gandjustas

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

回答by E. Nusinovich

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. Cast it to an unsigned integer, and you'll be fine.

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

回答by Franco Méndez

An intis equivalent to uint32_tand charto uint8_t.

一个int相当于uint32_tcharuint8_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. (Note: the protocol was to send 1024 bytes)

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

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

Hope it helps.

希望能帮助到你。

回答by HomDhi

You can simply use memcpyas follows:

您可以简单地使用memcpy如下:

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

回答by Dr. Sahib

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