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

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

但是,如果我使用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; } 

有了这个结构定义:

 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个字节具有不确定值。

评论者说,您提供的代码没有提供足够的信息来解决您的问题。 看起来错误在于代码中的其他位置。 我可以将您的代码转换为MCVE,如下所示:

 #include  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" (吹过字符串"John"NUL终结符并保存打印字符串时不会看到的垃圾值)。

新代码使用:

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

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

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

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

请注意,指针和int的大小在不同的系统上可能不同,并且完全可以为指针提供4个字节,为int 4个字节,留下2个字节,这些字节不是struct一部分。 此外,尽管这对您没有影响,但在struct的第一个成员之后可能存在填充。