震惊 居然是相同的结果 - HeavyYuan/A-CD-Record-Management-System GitHub Wiki
以下程序逻辑:
- 用户输入字符串
- 用用户数据赋值结构体
- 将结构题加入结构体数组
- 打印结构体数组中的所有元素
结果:
3个结构体元素的foo是相同的
struct Foo{
char *foo;
};
struct Foo *array[10] = {0};
void fulfil_array(char *str,struct Foo *foo, int index)
{
*foo = (struct Foo){
.foo = str
};
if(index > 2){
printf("%d, index illegal\n", index);
return;
}
array[index] = foo;
}
int my_test()
{
int i = 0;
while( i < 3 ){
char var[10];
printf("var: ");
scanf("%s",var);
struct Foo *foo = (struct Foo *)malloc(sizeof(struct Foo));
fulfil_array(var, foo, i);
i++;
}
}
void print_foo()
{
int i;
for(i = 0 ;i < 3; i++)
printf("array[%d] = %s\n",i,array[i]->foo);
}
int main(void)
{
my_test();
print_foo();
return 0;
}
原因:
my_test的while循环中,预期逻辑是:
- 声明一个字符数组
- 用户输入给其赋值
- 用字符数组赋值结构体
问题在于每次循环,var的值是相同的,都是同一个指针。 所以var是最后一次用户输入的值。
而在fulfil_array中,结构体的赋值是通过赋值符号直接赋值,因此赋值后foo和var都指向同一个位置。 所以在对var进行用户输入赋值时,实际上也就改变了foo所指向的值。
修改方法:
将对结构体元素foo的赋值方法修改成字符拷贝(strncpy)
这里有新的问题,对于char *foo
,其必须先malloc
之后再做strncpy
从看qemu和内核的经验,结构体中的字符串声明一般用char foo[MAX_LEN]的方式,这样就可以直接做strncpy
唱片项目也遇到以上问题,也做了如上的修改方式。见commit 3cbcf488d611085a9b0fa07821f85a152e50ec7d