[英]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
语句中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]);
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_t
, char
等于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.