将一个int转换为一个4字节的char数组(C)
嘿,我正在寻找将用户input的int转换为4字节,我分配给一个字符数组。 如何才能做到这一点?
例:
转换175的用户input
00000000 00000000 00000000 10101111
到目前为止所有答案的问题,转换255应该会导致0 0 0 ff
尽pipe它打印出来: 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,当input输出为0, 0, 0, ffffffaf
时,它应该只是0, 0, 0, ffffffaf
0, 0, 0, af
这样做的便携方式(确保你得到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;
使用联合和memcpy()
将在不同的机器上得到不同的结果。
你遇到的问题是打印而不是转换。 我认为你使用的是char
而不是unsigned char
,而你使用这样的一行来打印它:
printf("%x %x %x %x\n", bytes[0], bytes[1], bytes[2], bytes[3]);
当任何窄于int
types被传递给printf
,它们被提升为int
(或者unsigned int
,如果int
不能保存原始types的所有值)。 如果char
在你的平台上被签名,那么0xff
可能不适合该types的范围,它被设置为-1而不是2s-complement机器上的表示0xff
。
-1被提升为一个int
,并且在你的机器上有一个表示forms0xffffffff
,这就是你所看到的。
你的解决scheme是要么实际使用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]);
你想解决一个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以反映无符号值。
在你的问题中,你说你想把175的用户input转换为00000000 00000000 00000000 10101111
,这是大端字节sorting,也就是所谓的networking字节顺序 。
把你的无符号整数转换成一个大的无符号字符数组是一种非常便于使用的方法,就像你给出的那个“175”的例子所说的那样,将使用C的htonl()
函数(在头文件<arpa/inet.h>
在Linux系统上)将unsigned int转换成big endian字节顺序,然后使用memcpy()
(在C的头文件<string.h>
定义C ++的<cstring>
)将字节复制到char(或unsigned char )数组。
htonl()
函数接受一个无符号的32位整数作为参数(与htons()
相反, htons()
接受一个无符号的16位整数),并将其从主机字节顺序转换为networking字节顺序(因此是首字母缩写词,主机到networking长,主机到networking短路),返回结果作为一个无符号的32位整数。 这一系列function的目的是确保所有的networking通信都以大的字节顺序进行,这样所有的机器都可以通过一个套接字相互通信,而不会出现字节顺序问题。 (另外,对于big-endian机器来说, 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; }
请注意,如上所述,必须使用printf的%x
格式说明符将字符打印为无符号字符。
上面的代码在我的机器上打印0 0 0 af
(一个x86_64机器,它使用小端字节sorting),它是hex的175。
你可以试试:
void CopyInt(int value, char* buffer) { memcpy(buffer, (void*)value, sizeof(int)); }
int a = 1; char * c = (char*)(&a); //In C++ should be intermediate cst to void*
为什么你需要一个中间转换来在C ++中void *因为cpp不允许在指针之间直接转换,所以你需要使用reinterpret_cast或者cast来void *做这件事情。
转换的问题(它最后给你一个ffffff的原因)是因为你的hex整数(你使用&二进制运算符)被解释为被签名。 将其转换为无符号整数,就可以了。
一个int
等同于uint32_t
和char
to uint8_t
。
我将展示如何解决客户端 – 服务器通信,以1位数组的forms发送实际时间(4个字节,以Unix纪元格式化),然后在另一侧重新构build它。 (注意:协议是发送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);
希望能帮助到你。
问题在于无符号字符是一个4字节的数字而不是许多人认为的1字节数字,因此将其更改为
union { unsigned int integer; char byte[4]; } temp32bitint;
并在打印时进行投射,以防止提升为“int”(默认为C)
printf("%u, %u \n", (unsigned char)Buffer[0], (unsigned char)Buffer[1]);