[英]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 个字节包含字符J
、 o
、 h
、 n
然后跟在作为字符串终止符的 NUL 字符之后,然后跟在 15 个字节的未确定值之后。 然后跟随代表age
4 个字节。
在这种情况下, fwrite(&p1, 1, 10, fp);
将再次从p1
的内存地址开始写入 10 个字节,但如上段所述,前 4 个字节包含“John”,第 5 个字节包含 NUL 终止符,其余 5 个字节的值不确定。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.