如何将 "hexadecimal" 个数字 [C/Linux] 的 char[4] 转换为整数

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是17480 insead of 68

更新:Nvm。我解决了。我在移动时混合了索引。它应该是 value[1] << 8 ... |值[0]

假设您指向缓冲区:

unsigned char *p = &buf[20];

并且您想将接下来的 4 个字节视为一个整数并将它们分配给您的整数,那么您可以 cast it:

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++;

一般注意事项

这个问题似乎有几个部分 -- 至少是如何读取数据、使用什么数据类型来保存中间结果以及如何执行转换。如果您确实假设文件上的表示形式由 little-endian 顺序的 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 ... */ }

正在转换数据

了解文件上的表示是否与主机的字节顺序相匹配是值得的,因为如果匹配,则您不需要进行任何转换(也就是说,在这种情况下,您此时已完成)。但是,如果 do 需要交换字节顺序,则可以使用 ntohl()htonl():

if (!host_is_little_endian) {
    data = ntohl(data);
}

(假设小端和大端是您唯一需要关注的主机字节顺序。历史上还有其他的,这就是字节重新排序函数成对出现的原因,但您极不可能见到其他人之一。)

有符号整数

如果您需要有符号整数而不是无符号整数,那么您也可以这样做,但要使用联合:

union {
    uint32_t unsigned;
    int32_t signed;
} data;

以上都是用data.unsigned代替普通的data,最后从data.signed中读出签名后的结果。