问题
I am trying to a create a linked list. When I add to the list in the same function that I create the object in, it works.
Definitions:
typedef struct student {
int num;
char* name;
} student;
typedef struct container {
student* data;
struct container* next;
} container ;
All the objects I use are initialized like this:
student stu1;
stu1.num = 6;
stu1.name = "grefagf";
front = createContainer(&stu1);
back = front;
student stu2;
stu2.num = 3;
stu2.name = "dsghjyreawre";
student stu3;
stu3.num = 4;
stu3.name = "dsghhjrant";
student stu4;
stu4.num = 213;
stu4.name = "fdsafgrw";
When I add these elements to a list in the main function like this:
container* tmp;
tmp = createContainer(&stu2);
back->next = tmp;
back = tmp;
tmp = createContainer(&stu3);
back->next = tmp;
back = tmp;
tmp = createContainer(&stu4);
back->next = tmp;
back = tmp;
it works properly, outputting this:
1: 6 grefagf
2: 3 dsghjyreawre
3: 4 dsghhjrant
4: 213 fdsafgrw
when I print it using another function I made.
But if I create a function called add() and pass stu2, stu3..., like so:
int add(student to_add) {
container* tmp;
tmp = createContainer(&to_add);
printf("added: (%d, %s)\n", tmp->data->num, tmp->data->name);
back->next = tmp;
back = tmp;
return 1;
}
then do this in the main function:
add(stu2);
add(stu3);
add(stu4);
it outputs this:
1: 6 grefagf
2: 41096808 fdsafgrw
3: 41096808 fdsafgrw
4: 41096808 fdsafgrw
Heres the source in case you need it:
Non-function example: https://pastebin.com/ZLqTzp4t
#include <stdio.h>
#include <stdlib.h>
typedef struct student {
int num;
char* name;
} student;
typedef struct container {
student* data;
struct container* next;
} container ;
container* back;
container* front;
container* createContainer(student* data) {
container* tmp = malloc(sizeof(container));
tmp->data = data;
tmp->next = NULL;
return tmp;
}
void printList(container* front) {
container* tmp = front;
int i;
i=0;
while (tmp != NULL) {
i++;
printf("%d:\t%d\t\t%s\n", i, tmp->data->num, tmp->data->name);
tmp = tmp->next;
}
}
int main(void) {
student stu1;
stu1.num = 6;
stu1.name = "grefagf";
front = createContainer(&stu1);
back = front;
student stu2;
stu2.num = 3;
stu2.name = "dsghjyreawre";
student stu3;
stu3.num = 4;
stu3.name = "dsghhjrant";
student stu4;
stu4.num = 213;
stu4.name = "fdsafgrw";
container* tmp;
tmp = createContainer(&stu2);
back->next = tmp;
back = tmp;
tmp = createContainer(&stu3);
back->next = tmp;
back = tmp;
tmp = createContainer(&stu4);
back->next = tmp;
back = tmp;
printf("front\n");
printList(front);
printf("\ntop\n");
printList(back);
return EXIT_SUCCESS;
}
Function example: https://pastebin.com/TyQY4j5k
#include <stdio.h>
#include <stdlib.h>
typedef struct student {
int num;
char* name;
} student;
typedef struct container {
student* data;
struct container* next;
} container ;
container* back;
container* front;
container* createContainer(student* data) {
container* tmp = malloc(sizeof(container));
tmp->data = data;
tmp->next = NULL;
return tmp;
}
int add(student to_add) {
container* tmp;
tmp = createContainer(&to_add);
printf("added: (%d, %s)\n", tmp->data->num, tmp->data->name);
back->next = tmp;
back = tmp;
return 1;
}
void printList(container* front) {
container* tmp = front;
int i;
i=0;
while (tmp != NULL) {
i++;
printf("%d:\t%d\t\t%s\n", i, tmp->data->num, tmp->data->name);
tmp = tmp->next;
}
}
int main(void) {
student stu1;
stu1.num = 6;
stu1.name = "grefagf";
front = createContainer(&stu1);
back = front;
student stu2;
stu2.num = 3;
stu2.name = "dsghjyreawre";
student stu3;
stu3.num = 4;
stu3.name = "dsghhjrant";
student stu4;
stu4.num = 213;
stu4.name = "fdsafgrw";
add(stu2);
add(stu3);
add(stu4);
printf("front\n");
printList(front);
printf("\ntop\n");
printList(back);
return EXIT_SUCCESS;
}
回答1:
OK i tried it is working. Only get by address student structs to your add function as below
add(&stu2);
add(&stu3);
add(&stu4);
and change function of add as below
int add(student *to_add) {
container* tmp;
tmp = createContainer(to_add);
printf("added: (%d, %s)\n", tmp->data->num, tmp->data->name);
back->next = tmp;
back = tmp;
return 1;
}
回答2:
Here's a more or less minimal version of your code with the add function. It runs at 60 lines compared to 83 for your original.
#include <stdio.h>
#include <stdlib.h>
typedef struct student
{
int num;
char *name;
} student;
typedef struct container
{
student *data;
struct container *next;
} container;
static container *back;
static container *front;
static container *createContainer(student *data)
{
container *tmp = malloc(sizeof(container));
tmp->data = data;
tmp->next = NULL;
return tmp;
}
static void add(student to_add)
{
container *tmp = createContainer(&to_add);
printf("added: (%d, %s)\n", tmp->data->num, tmp->data->name);
back->next = tmp;
back = tmp;
}
static void printList(container *item)
{
for (int i = 0; item != NULL; item = item->next)
printf("%d:\t%d\t\t%s\n", ++i, item->data->num, item->data->name);
}
int main(void)
{
student stu1 = { 6, "grefagf" };
student stu2 = { 3, "dsghjyreawre" };
student stu3 = { 4, "dsghhjrant" };
student stu4 = { 213, "fdsafgrw" };
front = createContainer(&stu1);
back = front;
add(stu2);
add(stu3);
add(stu4);
printf("front\n");
printList(front);
printf("\nback\n");
printList(back);
return EXIT_SUCCESS;
}
On my Mac, it produced:
added: (3, dsghjyreawre)
added: (4, dsghhjrant)
added: (213, fdsafgrw)
front
1: 6 grefagf
2: 0
3: 0
4: 0
back
1: 0
The problem is that you are passing the address of a local variable to your createContainer() function, but that variable goes out of scope so your container is pointing at garbage. Since this is invoking undefined behaviour, the results can be different on your machine, and both will be correct. A crash is also possible — that's one of the beauties of UB.
You need to revise it in one of two ways. Either createContainer() makes a copy of what it is passed, or you arrange to pass pointers to the variables in main() through add() to createContainer(). This code does the second — but it is probably not the better solution in the long run. However, there's (a lot) more memory management to deal with for a general solution copying what's passed.
#include <stdio.h>
#include <stdlib.h>
typedef struct student
{
int num;
char *name;
} student;
typedef struct container
{
student *data;
struct container *next;
} container;
static container *back;
static container *front;
static container *createContainer(student *data)
{
container *tmp = malloc(sizeof(container));
tmp->data = data;
tmp->next = NULL;
return tmp;
}
static void add(student *to_add)
{
container *tmp = createContainer(to_add);
printf("added: (%d, %s)\n", tmp->data->num, tmp->data->name);
back->next = tmp;
back = tmp;
}
static void printList(container *item)
{
for (int i = 0; item != NULL; item = item->next)
printf("%d:\t%d\t\t%s\n", ++i, item->data->num, item->data->name);
}
int main(void)
{
student stu1 = { 6, "grefagf" };
student stu2 = { 3, "dsghjyreawre" };
student stu3 = { 4, "dsghhjrant" };
student stu4 = { 213, "fdsafgrw" };
front = createContainer(&stu1);
back = front;
add(&stu2);
add(&stu3);
add(&stu4);
printf("front\n");
printList(front);
printf("\nback\n");
printList(back);
return EXIT_SUCCESS;
}
There are 5 characters different here from the last version. There's a * in the function definition of add(); there's no & in the call to createContainer(); there is an & in each of the calls to add() in main(). The result is:
added: (3, dsghjyreawre)
added: (4, dsghhjrant)
added: (213, fdsafgrw)
front
1: 6 grefagf
2: 3 dsghjyreawre
3: 4 dsghhjrant
4: 213 fdsafgrw
back
1: 213 fdsafgrw
This code leaks memory because it doesn't attempt to clean up the list. That's OK for the time being. Just be aware that you'll need to clean up eventually.
回答3:
The add function should also consume the linked list (or "container") that it is adding the "student" to.
Thus, you should not be creating a "temp" container in it, but using the passed in container and adding to the back of that passed in container.
EDIT: Just realized your back and front are global. This probably isn't a good idea, because that way you can only have a single linked list for your entire program.
Rereading now...
EDIT 2: Ahh this was a good one. You are passing in student (which makes a copy of the student) and then taking its address in the add function, which is an address of a variable on the stack. The stack is popped off so address to variables on the stack don't make sense. Instead, add should take in a pointer to a student, and you should pass in the address of stu2, stu3, etc.
EDIT 3: Ahh too late :(
来源:https://stackoverflow.com/questions/48735436/why-can-i-not-add-to-a-linked-list-correctly-when-using-a-function