繁体   English   中英

将字符指针作为结构成员写入文件问题

[英]Writing char pointer as struct member to file issue

我有一个 struct 成员作为 char * 并将其分配给结构初始化时的字符串文字“John”,如下所示。 字符串用 printf 打印得很好。

但是,如果我使用 fwrite 将此字符串写入文件,则在文件中我会读回垃圾。

如果我使用 char 数组而不是 char *(在结构中注释掉,如图所示),并将其写入文件,我可以按预期读回文件中的字符串。 我无法理解这一点。 在这两种情况下, fwrite 不应该采用指针并将正确的字符串写入文件吗?

此外,如果我声明一个单独的 char * 并将其指向一个字符串文字并将其写入文件,我可以按预期读取它。 非常感谢您对解释的任何帮助。 (我在 Windows 上使用带有 Mingw 编译器的代码块 IDE)。

更新:包括使用的实际代码

int main()
{
    struct person
    {
        //char name[20];
        char* name;
        int age;
    };

    struct person p1 = {"John", 25};

    printf("%s\n", p1.name);
    FILE* fp = fopen("test.txt", "w");
    fwrite(&p1, 1, 10, fp);
    fclose(fp);
    return 0;
}

评论者说您提供的代码没有提供足够的信息来解决您的问题。 看起来错误出在您代码的其他地方。 我可以像这样将您的代码转换为MCVE

#include <stdio.h>

struct person
{
    //char name[20];
    char* name;
    int age;
};

int main(void)
{
    struct person p1 = {"John", 25};

    printf("%s\n", p1.name);

    FILE *fp = fopen("test.txt", "w");
    fwrite(p1.name, 1, 10, fp);
    fclose(fp);

    char buffer[20];
    fp = fopen("test.txt", "r");
    fread(buffer, 1, 10, fp);
    fclose(fp);

    printf("The stored name is: %s\n", buffer);

    return 0;
}

但我确信你所拥有的不同,因为这段代码有效:

John
The stored name is: John

更新

从您提供的新代码中,我可以看到您的问题是您将struct的内容写入文件,而不是将字符串写入文件,如原始代码示例中所示。

使用的原始代码:

fwrite(p1.name, 1, 10, fp);

并将字符串p1.name 10 个字节p1.name文件"test.txt" (正好经过字符串"John"NUL终止符并保存在打印字符串时看不到的垃圾值)。

新代码使用:

fwrite(&p1, 1, 10, fp);

struct p1的前 10 个字节保存到文件"test.txt"

struct包含char name[20]; ,前 10 个字节是存储在字符数组name中的char ,这就是您的代码在这种情况下似乎可以工作的原因。

struct包含char *name; ,保存的前几个字节属于指针name (在我的系统上为 8 个字节),而不是字符串文字"John" 接下来的几个字节属于int age (我系统上的 4 个字节)。 在这种情况下保存的是这些值,而不是字符串文字"John"char

请注意,指针和int的大小在不同的系统上可能不同,并且完全可能有 4 个字节的指针和 4 个字节的int ,留下 2 个不属于struct字节被保存。 此外,虽然这不会影响您,但在struct的第一个成员之后可能会有填充。

有了这个结构定义:

struct person
{
    char* name;
    int age;
};

下面的代码不会做你所期望的:

struct person p1 = {"John", 25};

printf("%s\n", p1.name);
FILE* fp = fopen("test.txt", "w");
fwrite(&p1, 1, 10, fp);

原因是变量p1字节实际上并不包含字符串“John”,但它包含一个指向字符串“John”的指针,即字符串“John”的内存地址。 现在fwrite(&p1, 1, 10, fp); 将从p1的内存地址开始写入 10 个字节,即(假设是 32 位系统):4 个字节表示指针,它只是某个内存地址,4 个字节表示1 (年龄)和 2 个字节在内存中不'不属于p1变量。

现在,如果结构是这样定义的:

struct person
{
    char name[20];
    int age;
};

情况完全不同。 这次变量p1实际上确实包含字符串“John”。 前 4 个字节包含字符John然后跟在作为字符串终止符的 NUL 字符之后,然后跟在 15 个字节的未确定值之后。 然后跟随代表age 4 个字节。

在这种情况下, fwrite(&p1, 1, 10, fp); 将再次从p1的内存地址开始写入 10 个字节,但如上段所述,前 4 个字节包含“John”,第 5 个字节包含 NUL 终止符,其余 5 个字节的值不确定。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM