将char指针编写为文件问题的结构成员

时间:2016-12-08 15:00:52

标签: c pointers struct char fwrite

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

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

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

此外,如果我声明一个单独的char *并将其指向字符串文字并将其写入文件,我可以按预期读回。非常感谢您提供任何解释帮助。 (我在Windows上使用带有Mingw编译器的codeblocks 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);
    return 0;
}

2 个答案:

答案 0 :(得分:3)

评论者说,您提供的代码没有提供足够的信息来解决您的问题。看起来错误在于代码中的其他地方。我可以将您的代码转换为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);

并将10个字节的字符串p1.name写入文件"test.txt"(向右吹过字符串NUL的{​​{1}}终结符并保存不会出现的垃圾值看到打印字符串)。

新代码使用:

"John"

fwrite(&p1, 1, 10, fp); struct的前10个字节保存到文件p1

"test.txt"包含struct时,前10个字节是char name[20];存储在字符数组char中,这就是为什么您的代码似乎在此工作的原因情况下。

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

请注意,指针和char的大小在不同的系统上可能不同,并且指针有4个字节,"John"有4个字节,剩下2个字节保存不属于int的一部分。此外,虽然这对您没有影响,但在int的第一个成员之后可能会有填充。

答案 1 :(得分:3)

使用此结构定义:

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 (年龄)和内存中跟随的不属于1变量的2个字节。

现在,如果结构定义如下:

p1

情况完全不同。这次变量struct person { char name[20]; int age; }; 实际上包含字符串“John”。前4个字节包含字符p1Joh,然后是NUL字符,它是字符串终止符,然后跟随15个字节的未确定值。然后按照4个字节代表n

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