结构体中的指针变量申请空间问题

C语言 码拜 8年前 (2017-04-11) 2962次浏览
本人声明了一个结构体包含id,age,name三个属性
struct studentInfo
{
int id;
int age;
char *name[20];
};
本人又创建了一个双向循环链表链表的每个节点的数据域是一个学生的信息;
然后希望遍历链表输出学生信息;
但是为姓名属性申请空间好像有问题,每次输出都是最后一个输入的学生的姓名,年龄和id都对;
代码如下:
#include<stdio.h>
#define ERROR -1
#define OK 0
#define NOTEXIST 1
typedef int State;
struct studentInfo
{
int id;
int age;
char *name;
};
struct Node
{
struct studentInfo student;
struct Node *prior;
struct Node *next;
}Node;
typedef struct Node * LinkList;
//创建链表
State createLinkList(LinkList *L) {
(*L) = (LinkList)malloc(sizeof(Node));
if ((*L) == NULL)
return ERROR;
(*L)->next = (*L);
(*L)->prior = (*L);
return OK;
}
//向链表中添加数据
//链表中添加数据有两种方式
//一种头插法一种尾插法
//尾插法需要寻找链表尾部
State addDataFirst(LinkList *L, struct studentInfo student) {
LinkList p;
p = (LinkList)malloc(sizeof(Node));
p->student = student;
p->next = (*L)->next;
(*L)->next->prior = p;
(*L)->next = p;
p->prior = (*L);
printf(“%d,%d,%s\n”, student.id, student.age, student.name);
return OK;
}
State addDataLast(LinkList *L, struct studentInfo student) {
LinkList p;
p = (LinkList)malloc(sizeof(Node));
p->student = student;
(*L)->prior->next = p;
p->prior = (*L)->prior;
(*L)->prior = p;
p->next = (*L);
printf(“%d,%d,%s\n”, student.id, student.age, student.name);
return OK;
}
int main() {
struct studentInfo student;
LinkList L;
LinkList p;
State state = 0;
createLinkList(&L);
student.name = (char *)malloc(20 * sizeof(char));
scanf(“%d,%d,%s”, &student.id,&student.age,student.name);
state = addDataLast(&L, student);
if (!state)
printf(“Add student sucessed!\n”);
scanf(“%d,%d,%s”, &student.id, &student.age, student.name);
state = addDataFirst(&L, student);
if (!state)
printf(“Add student sucessed!\n”);
p = L->next;
while (p != L) {
student = p->student;
printf(“%d,%d,%s\n”, student.id, student.age, student.name);
p = p->next;
}
return OK;
}
运行结果:
结构体中的指针变量申请空间问题
但是,假如将name属性声明为一个数组,主函数中不为它申请空间,就不会报错;
代码:
struct studentInfo
{
int id;
int age;
char name[20];
};
本人想提问,假如本人想把name声明为指针,本人该怎么样解决这个问题;还有就是这两种做法的区别在哪里,本人声明为指针的做法错误在哪里。
解决方案

1

你声明的是指针数组了,改成char* name即可。

1

创建链表的
(*L)->next = (*L);
(*L)->prior = (*L);
return OK;
就是几句废话
等于空不行吗?
(*L)->next =NULL;
(*L)->prior =NULL;
本人等于本人,又要二次分配Name
你丫就不当心重复分配

2

char *name[20];  改成 char *name;

20

哥们,出现你上面那个结果是原因是深拷贝的问题导致得
1.你对student.name在main()中申请了一片空间,注意只是一片空间,当你第一次赋值之后,你传入了函数(进行的是值传递,也就是说只是传了student.name指针的副本,没有在单独开辟空间出来),此时你直接赋值给另一个结构体(由于你结构体没有等号操作符重载,因此采用默认的,只进行值得赋值,因此就只是student.name的指针本身的值付给它,并没有开辟另外的空间,暂记这个指针ptr,指向A空间)。当你第二次传递进来的时候一样的传递ptr指针,而同样进行值赋值没创建空间。因此你第一次与第二次传递的都是ptr指针,指向的空间都是A,当你第二次重新赋值了A空间后,那么第一次同样也是指向了这个空间,那么就是第一次、第二次指向同样空间 ,里面的值当然以第二次为准,所以打印结果相同
2.基本数据类型这不一样,没有深拷贝,直接赋值即可,显示结果就不同了
3.你将char* 换成char数组当然就可以了,原因是char数组初始化结构体时就会申请出空间,那么两次就是不同的空间了,就可以保存不同的值了
嘿嘿!不好意,第一次在这上面回答问题,说的不清楚,还望谅解

1

楼上解释正确。简单说就是, 每个节点的name都指向最初malloc的那段空间。

12

引用:
Quote: 引用:

char *name[20];  改成 char *name;

粘程序粘错了,本人声明的是char *name;但是出现了如题的问题

假如是指针,对象复制、赋值需要深拷贝,默认的是浅拷贝,也就是只是复制指针的值,并没重新申请一片内存,而假如是数组的话,会复制整个数组

10

假如定义的是char*name,那么添加新节点时需要新开辟一段空间,例如malloc(20*sizeof(char)),而不只是简单的开辟结构体空间,然后直接把传进来的结构体付给他那么简单,那样的话,你结构体里的name指针只是指向了一个临时参数里的空间,函数结束就无效了,所以出现了错误。
假如你定义的是字符数组char name[20]那就没有什么问题了

CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明结构体中的指针变量申请空间问题
喜欢 (0)
[1034331897@qq.com]
分享 (0)