【问题标题】:Problem writing int to binary file in C在 C 中将 int 写入二进制文件的问题
【发布时间】:2010-10-20 19:16:50
【问题描述】:

我需要使用 C 的 I/O 函数将数据写入二进制文件。以下代码导致运行时异常:


#include "stdio.h"

int main(int argc,char* argv[]) {
    FILE *fp = fopen("path_to_file.bin","wb");
    if(fp == NULL) {
        printf("error creating file");
        return -1;
    }
    int val = 4;
    fwrite((const void*)val,sizeof(int),1,fp);
    fclose(fp);
    return 0;
}

代码在 fwrite 处死掉。你能看出我做错了什么吗?显然,我正在尝试访问 0x0000004 或类似位置的数据。

谢谢!

【问题讨论】:

    标签: c file binary int


    【解决方案1】:

    我认为尼尔的回答可以改进。我意识到它已经被接受了,所以这只是为了显示一些对比(这就是我不只是编辑他的原因)。

    fwrite(&val, sizeof val, 1, fp);
    

    两个改进:

    • 没有指针转换,因为它在 C 中不是必需的并且可以隐藏错误。
    • 直接在对象上使用sizeof,因为这是您传递指针的对象。对我来说很有意义,而且比重复自己和使用类型名称更安全。

    【讨论】:

    • +1 都不错。故事的寓意:喜欢少演员,明智地使用 sizeof。
    • 你能解释一下为什么不需要演员表吗?我不是 C 程序员……我想尽可能多地了解它的“魔力”。
    • fwrite() 需要一个 void* 作为它的第一个参数。任何指针类型都可以在不需要强制转换的情况下使用 void*。 void* 有效地表示“我需要一个指针,我不在乎它指向什么类型”。
    • C 中不需要。尤其是指针。您可以将指向 void 的指针分配给指向任何对象类型的指针,反之亦然
    【解决方案2】:
     fwrite((const void*)val,sizeof(int),1,fp);
    

    应该是:

     fwrite((const void*) & val,sizeof(int),1,fp);
    

    顺便说一句,如果你不使用演员表,你会得到一个合理的错误信息。 C(和 C++)程序员使用类型转换的次数往往比他们应该使用的要多得多 - 一个好的经验法则是“如果它需要一个类型转换,它可能是错误的”。

    【讨论】:

    • + 该规则的另一个 1。我把它贴在我显示器上的便签上。
    【解决方案3】:

    补充尼尔的答案:当您在同一平台上读取和写入文件时,这有效。如果您在不同字节序的平台上读/写,事情可能会变得很奇怪。

    【讨论】:

    • 不仅字节序,大小也可能不同。
    • C 不是多平台,在文件写入/读取中,大多数时候您需要为每个平台进行实现,不同的行尾标记之类的事情在处理文件写入时会变成一场噩梦/跨平台阅读(无论如何有点离题:P)
    【解决方案4】:
    #include "stdio.h"
    
    int main(int argc,char* argv[]) {
        FILE *fp = fopen("path_to_file.bin","wb");
        if(fp == NULL) {
            printf("error creating file");
            return -1;
        }
        int val = 4;
        fwrite((const void*)val,sizeof(int),1,fp);
    

    你应该提供一个地址而不是整数本身。

    另外你不应该这样使用整数:

    1. 不同计算机上的字节序可能不同(如上所述)
    2. 它的大小可能不同。在非常旧的计算机上,它可能是 1 或 2 个字节。在最现代的情况下,它将是 4,但它可能也是 8(一些 64 位计算机)。在一些奇怪的架构上,它甚至可能是 36 位。 int32_t val = 4; fwrite((const void *)val, 4, 1, fp) 应该可以解决问题。

    您可能认为您的软件永远不需要移植。好吧 - 许多设计师(软件和硬件)做出了类似的假设。有时不制作它们的成本太高 - 但在这种情况下,只需进行少量额外检查即可。

        fclose(fp);
        return 0;
    }
    

    【讨论】:

      【解决方案5】:

      我也遇到过这种问题。所以这是我的解决方案。

      fwrite(val, sizeof(val[0], sizeof(val)/sizeof(val[0]), fp);

      【讨论】:

        【解决方案6】:

        显然,我正在尝试访问 0x0000004 或类似位置的数据。

        int val = 4
        

        问题来了。 fwrite 设计用于处理字符串,因此它的第一个输入是指针,即字符串在内存中的位置。您将val 的值直接(4)而不是val 的地址传递给fwrite;但是,0x00000004 处的内存不是有效的程序内存,因此会出现错误。

        要解决此问题,请更改以下内容:

        fwrite((const void*)val,sizeof(int),1,fp);
        

        进入这个:

        fwrite((const void*)&val, sizeof(int), 1, fp);
        

        “&”运算符表示val 的位置。这将是内存中的有效地址。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-12-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-02-18
          相关资源
          最近更新 更多