C语言 字符数组中的字节如何表示整数?



假设我有一个字符数组,我从二进制文件(像ext2格式的文件系统图像文件)中读取。

现在我需要读取从偏移字节1024开始的整数(<—这是从数据开始的偏移量)。有什么简单的方法吗?整数可以是任意数。所以我相信在我的系统(x86-64)上可以用4字节的整数表示。

我认为我需要使用strtol:

/* Convert the provided value to a decimal long */
char *eptr=malloc(4);// 4 bytes becuase sizeof int is 4 bytes
....
int valread=read(fd,eptr,4);//fd is to ext2 formatted image file (from file system)
result = strtol(eptr, &v, 10);

上面是long,所以这个数字表示32位整数吗?

eptr应该null终止吗?

正确与否?

我有一个字符数组,我从二进制文件(像ext2格式的文件系统图像文件)中读取。

以二进制模式打开文件

const char *file_name = ...;
FILE *infile = fopen(file_name, "rb");  // b is for binary
if (infile == NULL) {
fprintf(stderr, "Unable to open file <%s>.n", file_name);
exit(1);
}

我需要读取从偏移字节1024开始的整数…

long offset = 1024; 
if (fseek(infile, offset, SEEK_SET)) {
fprintf(stderr, "Unable to seek to %ld.n", offset);
exit(1);
} 

所以我相信在我的系统中可以用4字节的整数来表示

与其使用int,它可能与4字节不同,不如考虑int32_t<stdint.h>

int32_t data4;
if (fread(&data4, sizeof data4, 1, infile) != 1) {
fprintf(stderr, "Unable to read data.n");
exit(1);
} 

Endian的帐号。

由于文件数据为小端序,因此转换为本机端序。参见#include <endian.h>.

data4 = le32toh(data4);

完成后清理

// Use data4
fclose(infile);

我相信我需要使用strtol

strtol()检查字符串并返回long。文件数据是二进制而不是字符串。

strtol的情况下,通过查看一些代码可能更容易跟随。这里有一个非常简单的strtol函数:

int string_to_int(const char *string)
{
// The integer value we construct and return
int value = 0;
// Loop over all the characters in the string, one by one,
// until the string null-terminator is reached
for (unsigned i = 0; string[i] != ''; ++i)
{
// Get the current character
char c = string[i];
// Convert the digit character to its corresponding numeric value
int c_value = c - '0';
// Add the characters numeric value to the current value
value = (value * 10) + c_value;
// Note the multiplication with 10: That's because decimal numbers are base 10
}
// Now the string have been converted to its decimal integer value, return it
return value;
}

如果我们用字符串"123"调用它并展开循环会发生这样的事情:

// First iteration
char c = string[0];  // c = '1'
int c_value = c - '0';  // c_value = 1
value = (value * 10) + c_value;  // value = (0 * 10) + 1 = 0 + 1 = 1
// Second iteration
char c = string[0];  // c = '2'
int c_value = c - '0';  // c_value = 2
value = (value * 10) + c_value;  // value = (1 * 10) + 2 = 10 + 2 = 12
// Third iteration
char c = string[0];  // c = '3'
int c_value = c - '0';  // c_value = 3
value = (value * 10) + c_value;  // value = (12 * 10) + 3 = 120 + 3 = 123

在第四次迭代中,我们到达字符串空终止符,循环结束时value等于int的值123

我希望这能让你更清楚地了解字符串到数字的转换是如何工作的。


虽然上面是针对字符串的,但如果您读取现有int值的原始二进制位,那么您不应该调用strtol,因为数据不是字符串。

相反,您基本上将四个字节解释为单个32位值。

不幸的是,在不了解端序的情况下,要解释这些位是如何被解释的并不容易。

Endianness是字节的排序方式,以组成整数值。以(十六进制)数字0x01020304为例,它们可以存储为0x01,0x02,0x030x04(这被称为大端dian);0x04,0x03,0x020x01(这被称为little-endian)。

在小端系统上(通常的类似pc的系统),假设你有一个这样的数组:

char bytes[4] = { 0x04, 0x03, 0x02, 0x01 };

然后你可以复制到int:

int value;
memcpy(&value, bytes, 4);

,这将使int变量value等于0x01020304

最新更新