2014-09-21 146 views
1

我有两个系统。一个是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”,而它的出现,这个我稍后需要某种程度的帮助。但我不明白为什么它在我的系统上有所不同。

+0

*正是*他们在读什么,然后怎么样*究竟*他们是否使用过(问题的类型**代码**会很好地回答;你已经告诉过我们,现在*显示它*)。 – WhozCraig 2014-09-21 15:48:25

+0

用代码更新了我的问题,并得到了确切的结果。 – nim 2014-09-21 16:08:49

回答

2

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 charunsigned char酌情从来没有裸露char

*我想我可以挖掘出的标准来检查,如果这实际上是指定的,但在这一点上它只是一个微不足道的细节

+2

+1,当为调用准备参数时,在调用者中发生'char'到'int'。 'int'到'unsigned'然后发生在'printf'里面,它不能丢弃前面的位,所以你可以在输出中看到所有的FFFF。 – 2014-09-21 18:50:00

+0

感谢您的好解释。它是100%正确的,我可以通过在ARM平台上将'char'更改为'signed char'来验证它。现在两个系统都显示相同的输出。再次感谢! – nim 2014-09-21 21:39:12

相关问题