C 指针在传递给函数后未设置
C pointer does not get set after being passed to a function
所以我一直在努力学习 C 语言一段时间,但我终于碰壁了。我在网上发现了不同的练习题,我真的遇到了这个问题。
最初我在主函数中编写了这段代码,它运行良好并提供了所需的输出(这里是 正在运行的示例)
#include <stdio.h>
#include <stdlib.h>
typedef struct Student STUDENT;
typedef struct Teacher TEACHER;
typedef struct Course COURSE;
int addStudentToTree(STUDENT *students, STUDENT *newStudent, STUDENT *currentStudent);
void printStudents(STUDENT *s);
struct Student
{
int StudentNumber;
char FirstName[BUFSIZ];
STUDENT *left, *right;
};
struct Teacher
{
int TeacherNumber;
char FirstName[BUFSIZ];
TEACHER *left, *right;
};
struct Course
{
int CourseNumber;
char CourseName[BUFSIZ];
int SemesterNumber;
COURSE *left, *right;
};
int main()
{
FILE *db = fopen("DatabaseFile.txt", "r");
char line[BUFSIZ];
STUDENT *newStudent, *currentStudent, *students;
students = NULL;
if (db != NULL)
{
while (fgets(line, sizeof(line), db) != NULL)
{
if (line[0] == 'S')
{
newStudent = malloc(sizeof(STUDENT));
if (sscanf(line, "S %d %s", &newStudent->StudentNumber, newStudent->FirstName) == 2)
{
newStudent->left = NULL;
newStudent->right = NULL;
if (students == NULL)
{
students = newStudent;
}
else
{
currentStudent = students;
while(currentStudent)
{
if (newStudent->StudentNumber != currentStudent->StudentNumber)
{
if (newStudent->StudentNumber < currentStudent->StudentNumber)
{
if (currentStudent->left == NULL)
{
currentStudent->left = newStudent;
break;
}
else
{
currentStudent = currentStudent->left;
}
}
else
{
if (currentStudent->right == NULL)
{
currentStudent->right = newStudent;
break;
}
else
{
currentStudent = currentStudent->right;
}
}
}
}
}
}
}
}
}
printStudents(students);
}
它成功地填充了树,然后遍历它给出了以下输出:
Student Number: 203214 Student Name: Agneta
Student Number: 208214 Student Name: Janeta
Student Number: 213363 Student Name: Jill
Student Number: 215263 Student Name: Hansi
Student Number: 215363 Student Name: Laurent
Student Number: 228214 Student Name: James
现在练习题的一部分也将它移到函数中,这样一切都不会 运行 在 main 方法中。
我是这样做的:
#include <stdio.h>
#include <stdlib.h>
typedef struct Student STUDENT;
typedef struct Teacher TEACHER;
typedef struct Course COURSE;
int addStudentToTree(STUDENT *students, STUDENT *newStudent, STUDENT *currentStudent);
void printStudents(STUDENT *s);
struct Student
{
int StudentNumber;
char FirstName[BUFSIZ];
STUDENT *left, *right;
};
struct Teacher
{
int TeacherNumber;
char FirstName[BUFSIZ];
TEACHER *left, *right;
};
struct Course
{
int CourseNumber;
char CourseName[BUFSIZ];
int SemesterNumber;
COURSE *left, *right;
};
int main()
{
FILE *db = fopen("DatabaseFile.txt", "r");
char line[BUFSIZ];
STUDENT *newStudent, *currentStudent, *students;
students = NULL;
if (db != NULL)
{
while (fgets(line, sizeof(line), db) != NULL)
{
if (line[0] == 'S')
{
newStudent = malloc(sizeof(STUDENT));
if (sscanf(line, "S %d %s", &newStudent->StudentNumber, newStudent->FirstName) == 2)
{
newStudent->left = NULL;
newStudent->right = NULL;
addStudentToTree(students, newStudent, currentStudent);
}
}
}
}
printStudents(students);
}
int addStudentToTree(STUDENT *students, STUDENT *newStudent, STUDENT *currentStudent)
{
if (students == NULL)
{
students = newStudent;
return 1;
}
else
{
currentStudent = students;
while(currentStudent)
{
if (newStudent->StudentNumber != currentStudent->StudentNumber)
{
if (newStudent->StudentNumber < currentStudent->StudentNumber)
{
if (currentStudent->left == NULL)
{
currentStudent->left = newStudent;
return 1;
}
else
{
currentStudent = currentStudent->left;
}
}
else
{
if (currentStudent->right == NULL)
{
currentStudent->right = newStudent;
return 1;
}
else
{
currentStudent = currentStudent->right;
}
}
}
}
}
return 0;
}
现在问题来了。我传入指针 'students' ,第一次传递时它是一个空指针,并被函数中的 if 语句正确捕获。 newStudent 变量指向内存地址。
在这些行之后:
if (students == NULL)
{
students = newStudent;
return 1;
}
指针 'students' 现在指向一个实际地址。但是在返回到 main 方法中的 while 循环后,'students' 指针再次成为 NULL 指针。
作为附加信息,您可以看到放入这些 printf:
if (students == NULL)
{
printf("students: %p, newStudent: %p\n",students, newStudent );
students = newStudent;
printf("students: %p\n",students);
return 1;
}
产生这个输出:
students: 0x0, newStudent: 0x7fc6e2001200
students: 0x7fc6e2001200
students: 0x0, newStudent: 0x7fc6e2001800
students: 0x7fc6e2001800
students: 0x0, newStudent: 0x7fc6e2005200
students: 0x7fc6e2005200
students: 0x0, newStudent: 0x7fc6e2005800
students: 0x7fc6e2005800
students: 0x0, newStudent: 0x7fc6e2005e00
students: 0x7fc6e2005e00
students: 0x0, newStudent: 0x7fc6e2006400
students: 0x7fc6e2006400
我真的花了很多时间在这上面,终于屈服了,来这里问问大家。
如果您还需要澄清这个问题,请告诉我。
彼得
你需要传递指针的地址...在这种情况下,参数是在堆栈上创建的,当函数退出时,堆栈被展开并且你的参数不再有效
int addStudentToTree(STUDENT **students, STUDENT *newStudent, STUDENT *currentStudent);
像
一样打电话
addStudentToTree(&students,newStudent,currentStudent);
在函数中像
*sudents=NULL;
希望对您有所帮助
想象一下:
void func(int var)
{
var = 1;
}
int main()
{
int var = 0;
func(var);
// What is the value of 'var' at this point?
...
}
如果您对上述问题的回答是1
,那么您可能应该回到基础知识,从头开始学习这门语言。
如果您确实了解函数 main
中变量 var
的副本保留其 "original" 值,那么您理解您分配给的任何值应该没有任何问题变量 students
在函数 printStudents
内的(副本)不会在该函数外生效。
也就是说,这里是通过引用传递此变量的一般准则:
- 函数声明中的变量类型加上
*
- printStudents(STUDENT** s)
- 将
*
添加到您在函数 printStudents
中对该变量所做的每个引用
- 在每个调用函数的地方在变量前加上
&
- printStudents(&s)
所以我一直在努力学习 C 语言一段时间,但我终于碰壁了。我在网上发现了不同的练习题,我真的遇到了这个问题。
最初我在主函数中编写了这段代码,它运行良好并提供了所需的输出(这里是 正在运行的示例)
#include <stdio.h>
#include <stdlib.h>
typedef struct Student STUDENT;
typedef struct Teacher TEACHER;
typedef struct Course COURSE;
int addStudentToTree(STUDENT *students, STUDENT *newStudent, STUDENT *currentStudent);
void printStudents(STUDENT *s);
struct Student
{
int StudentNumber;
char FirstName[BUFSIZ];
STUDENT *left, *right;
};
struct Teacher
{
int TeacherNumber;
char FirstName[BUFSIZ];
TEACHER *left, *right;
};
struct Course
{
int CourseNumber;
char CourseName[BUFSIZ];
int SemesterNumber;
COURSE *left, *right;
};
int main()
{
FILE *db = fopen("DatabaseFile.txt", "r");
char line[BUFSIZ];
STUDENT *newStudent, *currentStudent, *students;
students = NULL;
if (db != NULL)
{
while (fgets(line, sizeof(line), db) != NULL)
{
if (line[0] == 'S')
{
newStudent = malloc(sizeof(STUDENT));
if (sscanf(line, "S %d %s", &newStudent->StudentNumber, newStudent->FirstName) == 2)
{
newStudent->left = NULL;
newStudent->right = NULL;
if (students == NULL)
{
students = newStudent;
}
else
{
currentStudent = students;
while(currentStudent)
{
if (newStudent->StudentNumber != currentStudent->StudentNumber)
{
if (newStudent->StudentNumber < currentStudent->StudentNumber)
{
if (currentStudent->left == NULL)
{
currentStudent->left = newStudent;
break;
}
else
{
currentStudent = currentStudent->left;
}
}
else
{
if (currentStudent->right == NULL)
{
currentStudent->right = newStudent;
break;
}
else
{
currentStudent = currentStudent->right;
}
}
}
}
}
}
}
}
}
printStudents(students);
}
它成功地填充了树,然后遍历它给出了以下输出:
Student Number: 203214 Student Name: Agneta
Student Number: 208214 Student Name: Janeta
Student Number: 213363 Student Name: Jill
Student Number: 215263 Student Name: Hansi
Student Number: 215363 Student Name: Laurent
Student Number: 228214 Student Name: James
现在练习题的一部分也将它移到函数中,这样一切都不会 运行 在 main 方法中。
我是这样做的:
#include <stdio.h>
#include <stdlib.h>
typedef struct Student STUDENT;
typedef struct Teacher TEACHER;
typedef struct Course COURSE;
int addStudentToTree(STUDENT *students, STUDENT *newStudent, STUDENT *currentStudent);
void printStudents(STUDENT *s);
struct Student
{
int StudentNumber;
char FirstName[BUFSIZ];
STUDENT *left, *right;
};
struct Teacher
{
int TeacherNumber;
char FirstName[BUFSIZ];
TEACHER *left, *right;
};
struct Course
{
int CourseNumber;
char CourseName[BUFSIZ];
int SemesterNumber;
COURSE *left, *right;
};
int main()
{
FILE *db = fopen("DatabaseFile.txt", "r");
char line[BUFSIZ];
STUDENT *newStudent, *currentStudent, *students;
students = NULL;
if (db != NULL)
{
while (fgets(line, sizeof(line), db) != NULL)
{
if (line[0] == 'S')
{
newStudent = malloc(sizeof(STUDENT));
if (sscanf(line, "S %d %s", &newStudent->StudentNumber, newStudent->FirstName) == 2)
{
newStudent->left = NULL;
newStudent->right = NULL;
addStudentToTree(students, newStudent, currentStudent);
}
}
}
}
printStudents(students);
}
int addStudentToTree(STUDENT *students, STUDENT *newStudent, STUDENT *currentStudent)
{
if (students == NULL)
{
students = newStudent;
return 1;
}
else
{
currentStudent = students;
while(currentStudent)
{
if (newStudent->StudentNumber != currentStudent->StudentNumber)
{
if (newStudent->StudentNumber < currentStudent->StudentNumber)
{
if (currentStudent->left == NULL)
{
currentStudent->left = newStudent;
return 1;
}
else
{
currentStudent = currentStudent->left;
}
}
else
{
if (currentStudent->right == NULL)
{
currentStudent->right = newStudent;
return 1;
}
else
{
currentStudent = currentStudent->right;
}
}
}
}
}
return 0;
}
现在问题来了。我传入指针 'students' ,第一次传递时它是一个空指针,并被函数中的 if 语句正确捕获。 newStudent 变量指向内存地址。
在这些行之后:
if (students == NULL)
{
students = newStudent;
return 1;
}
指针 'students' 现在指向一个实际地址。但是在返回到 main 方法中的 while 循环后,'students' 指针再次成为 NULL 指针。
作为附加信息,您可以看到放入这些 printf:
if (students == NULL)
{
printf("students: %p, newStudent: %p\n",students, newStudent );
students = newStudent;
printf("students: %p\n",students);
return 1;
}
产生这个输出:
students: 0x0, newStudent: 0x7fc6e2001200
students: 0x7fc6e2001200
students: 0x0, newStudent: 0x7fc6e2001800
students: 0x7fc6e2001800
students: 0x0, newStudent: 0x7fc6e2005200
students: 0x7fc6e2005200
students: 0x0, newStudent: 0x7fc6e2005800
students: 0x7fc6e2005800
students: 0x0, newStudent: 0x7fc6e2005e00
students: 0x7fc6e2005e00
students: 0x0, newStudent: 0x7fc6e2006400
students: 0x7fc6e2006400
我真的花了很多时间在这上面,终于屈服了,来这里问问大家。 如果您还需要澄清这个问题,请告诉我。
彼得
你需要传递指针的地址...在这种情况下,参数是在堆栈上创建的,当函数退出时,堆栈被展开并且你的参数不再有效
int addStudentToTree(STUDENT **students, STUDENT *newStudent, STUDENT *currentStudent);
像
一样打电话addStudentToTree(&students,newStudent,currentStudent);
在函数中像
*sudents=NULL;
希望对您有所帮助
想象一下:
void func(int var)
{
var = 1;
}
int main()
{
int var = 0;
func(var);
// What is the value of 'var' at this point?
...
}
如果您对上述问题的回答是1
,那么您可能应该回到基础知识,从头开始学习这门语言。
如果您确实了解函数 main
中变量 var
的副本保留其 "original" 值,那么您理解您分配给的任何值应该没有任何问题变量 students
在函数 printStudents
内的(副本)不会在该函数外生效。
也就是说,这里是通过引用传递此变量的一般准则:
- 函数声明中的变量类型加上
*
-printStudents(STUDENT** s)
- 将
*
添加到您在函数printStudents
中对该变量所做的每个引用
- 在每个调用函数的地方在变量前加上
&
-printStudents(&s)