我有一个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;
}
答案 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个字节包含字符p1
,J
,o
,h
,然后是NUL字符,它是字符串终止符,然后跟随15个字节的未确定值。然后按照4个字节代表n
。
在这种情况下,age
将再次从fwrite(&p1, 1, 10, fp);
的内存地址开始写入10个字节,但如上段所述,前4个字节包含“John”,第5个字节包含NUL终结符和剩余的5个字节具有不确定的值。