嘿,我正在寻找将用户输入的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
答案 0 :(得分:130)
便携式执行此操作的方式(确保您到处获得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(其中的代表0xff
2s补充机器。)
-1升级为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]);
答案 1 :(得分: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]);
}
注意:更正了printf以反映无符号值。
答案 2 :(得分:6)
在您的问题中,您声明要将用户输入175转换为
00000000 00000000 00000000 10101111
, big endian 字节排序,也称为网络字节顺序。
可移植的方式将无符号整数转换为大端无符号字符数组,正如您在“175”示例中所建议的那样,将使用C的htonl()
函数(在Linux系统上的标头<arpa/inet.h>
中定义)将unsigned int转换为big endian字节顺序,然后使用memcpy()
(在标头<string.h>
中为C定义,<cstring>
for C ++)将字节复制到char(或unsigned char)数组中。
htonl()
函数接受无符号的32位整数作为参数(与htons()
相反,后者接收无符号的16位整数)并将其转换为网络字节顺序主机字节顺序(因此首字母缩写,主机TO网络长,而主机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
格式说明符将字符打印为无符号字符。
上面的代码在我的机器上打印0 0 0 af
(x86_64机器,它使用小端字节排序),这是175的十六进制。
答案 3 :(得分:2)
您可以尝试:
void CopyInt(int value, char* buffer) {
memcpy(buffer, (void*)value, sizeof(int));
}
答案 4 :(得分:1)
为什么在C ++中需要中间强制转换为void * 因为cpp不允许在指针之间进行直接转换,所以你需要使用reinterpret_cast或者转换为void *来做事情。
答案 5 :(得分:0)
int a = 1;
char * c = (char*)(&a); //In C++ should be intermediate cst to void*
答案 6 :(得分:-1)
转换的问题(它最后给你一个ffffff的原因)是因为你的十六进制整数(你正在使用&amp;二元运算符)被解释为被签名。将它转换为无符号整数,你会没事的。
答案 7 :(得分:-1)
int
相当于uint32_t
和char
相当于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);
希望它有所帮助。
答案 8 :(得分:-2)
问题出现了,因为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]);
答案 9 :(得分:-2)
您可以按如下方式简单地使用memcpy
:
unsigned int value = 255;
char bytes[4] = {0, 0, 0, 0};
memcpy(bytes, &value, 4);