C pread给出了不同的结果
我有两个系统。一个是Intel CPU上的Ubuntu 14.04 64bit,另一个是CubieTruck上的ARM 14.04。C pread给出了不同的结果
英特尔系统有一个存储在ext4格式化硬盘上的数据文件。 CubieTruck在与NTFS-3G一起安装的NTFS硬盘上具有相同的文件。
我目前在这些系统上有pread()问题。我从文件中读取了一堆字节,并从这个块中打印出第一个64字节。后来,这些字节被用来使用Shabal计算一些哈希值。
虽然打印在CubieTruck上的数据与使用十六进制编辑器打开文件时在Windows系统上看到的完全一致,但64位Ubuntu上的输出却不同。它看起来像是充满了“FFFFFF”,但一般来说也不同。更奇怪的是,尽管CubieTruck上的输出总是保持不变,但在一段时间后它会在64位的Ubuntu系统上发生变化(当我发现这种情况时我还没有看到过某种模式,我只是时不时地检查)。
但最令人讨厌的是,x64系统似乎可以正确计算,而ARM系统是错误的。
我不知道为什么pread会在这些系统下为同一个文件提供不同的结果,但我希望有人能够对此有所了解。
编辑,代码:
int main(int argc, char **argv) {
unsigned int readsize = 16384 * 32 * 2;
char *cache = (char*) malloc(readsize);
int fh = open("/home/user/somefile", O_RDONLY);
if (fh < 0) {
printf("can't open file");
exit(-1);
}
int bytes = 0, b;
do {
b = pread(fh, &cache[bytes], readsize - bytes, bytes);
bytes += b;
} while(bytes < readsize && b > 0);
int i = 0;
for (i=0; i < 64; i++) {
printf("%02X", cache[i]);
}
close(fh);
free(cache);
return 0;
}
两个系统都打开完全相同的文件。
结果在x64:在ARM FFFFFF94FFFFFFF16D25FFFFFFC0FFFFFFA3367D010BFFFFFFEF1E12FFFFFF841CFFFFFFBE4C26FFFFFF92FFFFFF80FFFFFF86FFFFFFA822FFFFFF8A26FFFFFF906CFFFFFFAD05FFFFFFE7FFFFFFB124FFFFFFA8FFFFFFF77B16FFFFFFEAFFFFFFACFFFFFF9DFFFFFF9EFFFFFF81FFFFFFC7FFFFFF92FFFFFFCDFFFFFFB0FFFFFFE86270FFFFFFF974FFFFFFA8420C45FFFFFFFC04FFFFFFF9103F2E3A47FFFFFF990F
结果: 94F16D25C0A3367D010BEF1E12841CBE4C26928086A8228A26906CAD05E7B124A8F77B16EAAC9D9E81C792CDB0E86270F974A8420C45FC04F9103F2E3A47990F
你可以看到,在x64,结果充满了 “FFFFFF”,而它的出现,这个我稍后需要某种程度的帮助。但我不明白为什么它在我的系统上有所不同。
C的一个有趣方面是实现定义的行为的数量 - 在本例中为whether char
is signed or not。
%x格式说明符采用unsigned int
参数,所以在ARM情况下,转换非常简单 - char
是无符号的,因此只需将零延伸到unsigned int
即可。然而,对于在那里的签署x86上,converion可以去以下两种方法之一:
- 的
char
符号扩展到signed int
,然后将其转换为unsigned int
- 第一投地
unsigned char
,然后零扩展到unisgned int
看来转换的煤焦> INT部分优先于人签署>无符号的一部分*让您获得前(注意如何字节没有最高位设置是明确的,并在两个实现上打印相同)。我想你的计算可能会在希望签名的地方进行类似的转换,这也是为什么它会在ARM上崩溃。
总之,如果你要处理的字符大小值而不是字符,总是指定signed char
或unsigned char
酌情从来没有裸露char
。
*我想我可以挖掘出的标准来检查,如果这实际上是指定的,但在这一点上它只是一个微不足道的细节
+1,当为调用准备参数时,在调用者中发生'char'到'int'。 'int'到'unsigned'然后发生在'printf'里面,它不能丢弃前面的位,所以你可以在输出中看到所有的FFFF。 – 2014-09-21 18:50:00
感谢您的好解释。它是100%正确的,我可以通过在ARM平台上将'char'更改为'signed char'来验证它。现在两个系统都显示相同的输出。再次感谢! – nim 2014-09-21 21:39:12
*正是*他们在读什么,然后怎么样*究竟*他们是否使用过(问题的类型**代码**会很好地回答;你已经告诉过我们,现在*显示它*)。 – WhozCraig 2014-09-21 15:48:25
用代码更新了我的问题,并得到了确切的结果。 – nim 2014-09-21 16:08:49