[英]Converting an int into a 4 byte char array (C)
嘿,我正在尋找將用戶輸入的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
這樣做的可移植方式(確保你到處都得到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
更窄的類型傳遞給printf
,它們將被提升為int
(或unsigned int
,如果int
不能保存原始類型的所有值)。 如果在您的平台上簽名char
,則0xff
可能不適合該類型的范圍,並且它被設置為-1(在2s補碼機器上具有表示0xff
)。
-1被提升為int
,並且在您的機器上具有表示0xffffffff
作為int
,這就是您所看到的。
您的解決方案是實際使用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]);
您想要解決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轉換為00000000 00000000 00000000 10101111
,這是大端字節排序,也稱為網絡字節順序 。
從你給出的“175”示例中建議的,將無符號整數轉換為大端無符號字符數組的大多數可移植方法是使用C的htonl()
函數(在頭文件<arpa/inet.h>
定義htonl()
在Linux系統上)將unsigned int轉換為big endian字節順序,然后使用memcpy()
(在C的頭文件<string.h>
定義,C ++的<cstring>
)將字節復制到char(或unsigned char) )數組。
htonl()
函數接受一個無符號的32位整數作為參數(與htons()
相反,后者采用無符號的16位整數)並將其從主機字節順序轉換為網絡字節順序(因此是首字母縮略詞) ,Host To Network Long,與Host TO Network Short for htons
),將結果作為無符號的32位整數返回。 此系列函數的目的是確保所有網絡通信都以大端字節順序發生,以便所有計算機可以通過套接字相互通信而不會出現字節順序問題。 ( htonl()
,對於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;
}
請注意,正如caf所說,您必須使用printf的%x
格式說明符將字符打印為無符號字符。
上面的代碼在我的機器上打印0 0 0 af
(x86_64機器,它使用小端字節排序),這是175的十六進制。
你可以試試:
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*
轉換的問題(它最后給你一個ffffff的原因)是因為你的十六進制整數(你正在使用&二元運算符)被解釋為被簽名。 將它轉換為無符號整數,你會沒事的。
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);
希望能幫助到你。
問題出現了,因為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]);
你可以簡單地使用memcpy
如下:
unsigned int value = 255;
char bytes[4] = {0, 0, 0, 0};
memcpy(bytes, &value, 4);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.