我最近一直试图刷新我的C并正在编写一个程序来手动解析PNG文件。
我在十六进制编辑器中查看了PNG文件,发现了一个看起来像
的字节流00 00 00 0D
以十六进制格式。
这个字符串应该代表我感兴趣的长度。
我使用getc(file)
来拉入PNG文件的字节。
我创建了一个char数组
char example[8];
存储从getc
检索到的字符。
现在,我填充了example
并用
printf("%#x, %#x, %#x, %#x", example[0]....
显示0, 0, 0, 0xd
,这正是我想要的。
但是当我使用
时int x = atoi(example)
或
int x = strtol(example, NULL, 16)
在这两种情况下我都回归零(我期待13)。我错过了一些基本的东西吗?
答案 0 :(得分:4)
atoi
将"0"
之类的字符串转换为数字等效字符,在本例中为0
。你所拥有的是字符串"\0\0\0\0\0\0\0\r"
,它远不是数字字符。
如果您想将字节解释为数字,可以执行类似
的操作char example[4] = {0, 0, 0, 0xd};
printf("%d\n", *(uint32_t*) example);
您会注意到(如果您使用的是x86 CPU),您将获得218103808
而不是13
由于端点很少:你走的越远,数字就越显着。
作为PNG uses big endian,您只需使用be32toh
(big endian来托管endianess):
uint32_t* n = example;
printf("%u\n", be32toh(*n)
答案 1 :(得分:2)
atoi
和strtol
期望文本字符串,而您有一个二进制值数组。要将数组中的各个字节组合为更大的整数,请尝试类似:
uint32_t x = (a[0] << 24) | (a[1] << 16) | (a[2] << 8) | a[3];
答案 2 :(得分:1)
atoi等对(ascii)字符串进行操作 你会得到123为“123”,这是字节49 50 41 0 你所拥有的是二元00 00 00 7B ......(而且,结束也很重要)。
简单,但在这种情况下错误的解决方案(忽略endianess):
将数组地址转换为int*
,然后使用*
获取值。
由于PNG中的整数在任何情况下都应该是大端,因此
指针转换只适用于大端机器。
作为便携式解决方案,将字节移位24,16,8,0并将二进制或二进制转换它们。