[英]How to convert to integer a char[4] of "hexadecimal" numbers [C/Linux]
所以我在 Linux 中處理系統調用。 我正在使用“lseek”來瀏覽文件並使用“read”來閱讀。 我還使用 Midnight Commander 查看十六進制文件。 我必須讀取的接下來的 4 個字節是 little-endian ,看起來像這樣:“2A 00 00 00”。 但當然,字節可以是“2A 5F B3 00”之類的東西。 我必須將這些字節轉換為整數。 我該如何處理? 我最初的想法是將它們讀入 4 個字符的向量,然后從那里構建我的整數,但我不知道如何。 有任何想法嗎?
讓我給你舉一個我嘗試過的例子。 我在文件“44 00”中有以下字節。 我必須將其轉換為值 68 (4 + 4*16):
char value[2];
read(fd, value, 2);
int i = (value[0] << 8) | value[1];
變量 i 是 68 的 17480。
更新:Nvm。 我解決了。 我在換班時混合了索引。 它應該是 value[1] << 8 ... | 值[0]
假設您指向緩沖區:
unsigned char *p = &buf[20];
並且您希望將接下來的 4 個字節視為整數並將它們分配給您的整數,然后您可以將其轉換:
int i;
i = *(int *)p;
你剛剛說 p 現在是一個指向 int 的指針,你取消引用那個指針並將它分配給 i。
但是,這取決於您平台的字節序。 如果您的平台具有不同的字節順序,您可能首先必須將字節反向復制到一個小緩沖區,然后使用此技術。 例如:
unsigned char ibuf[4];
for (i=3; i>=0; i--) ibuf[i]= *p++;
i = *(int *)ibuf;
Andrew Henle 和 Bodo 的建議和評論可以給出:
unsigned char *p = &buf[20]; int i, j; unsigned char *pi= &(unsigned char)i; for (j=3; j>=0; j--) *pi++= *p++; // and the other endian: int i, j; unsigned char *pi= (&(unsigned char)i)+3; for (j=3; j>=0; j--) *pi--= *p++;
這個問題似乎有幾個部分——至少如何讀取數據,使用什么數據類型來保存中間結果,以及如何執行轉換。 如果您確實假設文件上的表示由一個 32 位整數的字節組成,所有位都有意義,那么我可能不會使用char[]
作為中間,而是使用uint32_t
或int32_t
。 如果您知道或假設數據的字節序與機器的本機字節序相同,那么你不需要任何其他字節序。
如果您需要計算主機的本機字節序,則可以這樣做:
static const uint32_t test = 1;
_Bool host_is_little_endian = *(char *)&test;
這樣做是值得的,因為很可能您根本不需要進行任何轉換。
我會將數據讀入uint32_t
(或可能是int32_t
),而不是讀入char
數組。 可能我會將它讀入一個uint8_t
數組。
uint32_t data;
int num_read = fread(&data, 4, 1, my_file);
if (num_read != 1) { /* ... handle error ... */ }
了解文件表示是否與主機的字節序匹配是值得的,因為如果匹配,您不需要進行任何轉換(也就是說,在這種情況下,此時您已完成)。 但是,如果您確實需要交換字節順序,則可以使用ntohl()
或htonl()
:
if (!host_is_little_endian) {
data = ntohl(data);
}
(這假設小端和大端是您需要關注的唯一主機字節順序。從歷史上看,還有其他的,這就是字節重新排序函數成對出現的原因,但您極不可能看到其他之一。)
如果你需要一個有符號而不是無符號整數,那么你可以這樣做,但使用聯合:
union {
uint32_t unsigned;
int32_t signed;
} data;
以上都是用data.unsigned
代替plain data
,最后從data.signed
讀出有符號的結果。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.