我需要从二进制文件中读取32位指令。 所以我现在拥有的是:
unsigned char buffer[4];
fread(buffer,sizeof(buffer),1,file);
将在数组中放入4个字节
我该如何处理将这4个字节连接在一起以便以后处理32位指令? 或者我应该以不同的方式开始而不是使用fread?
我现在的奇怪方法是创建一个大小为32的整数数组,并用缓冲区数组中的位填充
答案 0 :(得分:1)
添加
unsigned int instruction;
memcpy(&instruction,buffer,4);
代码。这会将4个字节的缓冲区复制到一个32位变量中。因此,您将连接4个字节:)
答案 1 :(得分:1)
答案取决于32位整数如何存储在二进制文件中。 (我假设整数是无符号的,因为它确实是一个id,并使用uint32_t
中的<stdint.h>
类型。)
本机字节顺序数据在此计算机上以整数形式写出。只需使用fread
读取整数:
uint32_t op;
fread(&op, sizeof(op), 1, file);
基本原理:fread
将整数的原始表示读入内存。匹配fwrite
执行相反的操作:它将原始表示写入thze文件。如果您不需要在平台之间交换文件,这是存储和读取数据的好方法。
小端字节顺序数据存储为四个字节,最低有效字节优先:
uint32_t op = 0u;
op |= getc(file); // 0x000000AA
op |= getc(file) << 8; // 0x0000BBaa
op |= getc(file) << 16; // 0x00CCbbaa
op |= getc(file) << 24; // 0xDDccbbaa
基本原理:getc
读取一个字符并返回0到255之间的整数。(流用完且getc
返回负值EOF
的情况不在此处考虑简洁,即懒惰。)通过将您读取的每个字节移动8的倍数和/或它们与现有值来构建您的整数。评论概述了它的工作原理。正在阅读大写字母,小写字母已经存在。 Zeros尚未被分配。
大端字节顺序数据存储为四个字节,最后一个字节为最后一个字节:
uint32_t op = 0u;
op |= getc(file) << 24; // 0xAA000000
op |= getc(file) << 16; // 0xaaBB0000
op |= getc(file) << 8; // 0xaabbCC00
op |= getc(file); // 0xaabbccDD
基本原理:与上面几乎相同,只是你以另一种顺序移动字节。
你可以想象little-endian和big-endian将第一百二十二棵树(CXXIII)写成321或123.比特移位类似于在除以或乘以10的幂时移位十进制数字。 ,只是你把我的8位移位乘以2 ^ 8 = 256这里。
答案 2 :(得分:0)
如果您知道文件中的int与程序运行的机器具有相同的endian,那么您可以直接读入int。不需要char缓冲区。
unsigned int instruction;
fread(&instruction,sizeof(instruction),1,file);
如果您知道文件中int的endianness,而不知道程序运行的机器的endianness,那么您需要添加并将字节移位到一起。
unsigned char buffer[4];
unsigned int instruction;
fread(buffer,sizeof(buffer),1,file);
//big-endian
instruction = (buffer[0]<<24) + (buffer[1]<<16) + (buffer[2]<<8) + buffer[3];
//little-endian
instruction = (buffer[3]<<24) + (buffer[2]<<16) + (buffer[1]<<8) + buffer[0];
另一种想到这一点的方法是它是一个基数为256的位置数系统。就像你在基数10中组合数字一样。
257
= 2*100 + 5*10 + 7
= 2*10^2 + 5*10^1 + 7*10^0
所以你也可以使用Horner的规则来组合它们。
//big-endian
instruction = ((((buffer[0]*256) + buffer[1]*256) + buffer[2]*256) + buffer[3]);
//little-endian
instruction = ((((buffer[3]*256) + buffer[2]*256) + buffer[1]*256) + buffer[0]);
答案 3 :(得分:0)
@luser droog
您的代码中有两个错误。
变量“指令”的大小不得为4个字节:例如,Turbo C假定sizeof(int)为2。显然,在这种情况下,您的程序将失败。但是,更重要的是,不是那么显而易见:如果sizeof(int)超过4个字节,您的程序也会失败!要理解这一点,请考虑以下示例:
int main()
{ const unsigned char a[4] = {0x21,0x43,0x65,0x87};
const unsigned char* p = &a;
unsigned long x = (((((p[3] << 8) + p[2]) << 8) + p[1]) << 8) + p[0];
printf("%08lX\n", x);
return 0;
}
该程序在amd64下打印“ FFFFFFFF87654321”,因为使用时未签名的char变量将变为SIGNED INT!因此,将变量“指令”的类型从“ int”更改为“ long”并不能解决问题。
唯一的方法是编写如下内容:
unsigned long instruction;
instruction = 0;
for (int i = 0, unsigned char* p = buffer + 3; i < 4; i++, p--) {
instruction <<= 8;
instruction += *p;
}