所以我现在正在努力学习C,并且我有一些基本的结构问题我想清理一下:
基本上,所有内容都以这段代码为中心:
#include <stdio.h>
#include <stdlib.h>
#define MAX_NAME_LEN 127
typedef struct {
char name[MAX_NAME_LEN + 1];
unsigned long sid;
} Student;
/* return the name of student s */
const char* getName (const Student* s) { // the parameter 's' is a pointer to a Student struct
return s->name; // returns the 'name' member of a Student struct
}
/* set the name of student s
If name is too long, cut off characters after the maximum number of characters allowed.
*/
void setName(Student* s, const char* name) { // 's' is a pointer to a Student struct | 'name' is a pointer to the first element of a char array (repres. a string)
char temp;
int i;
for (i = 0, temp = &name; temp != '\0'; temp++, i++) {
*((s->name) + i) = temp;
}
/* return the SID of student s */
unsigned long getStudentID(const Student* s) { // 's' is a pointer to a Student struct
return s->sid;
}
/* set the SID of student s */
void setStudentID(Student* s, unsigned long sid) { // 's' is a pointer to a Student struct | 'sid' is a 'long' representing the desired SID
s->sid = sid;
}
我已经对代码进行了评论,试图巩固我对指针的理解;我希望他们都准确无误。
另外,我有另一种方法,
Student* makeAndrew(void) {
Student s;
setName(&s, "Andrew");
setStudentID(&s, 12345678);
return &s;
}
我肯定在某种程度上是错的......我也认为我的setName实现不正确。
任何指针? (没有双关语)
答案 0 :(得分:3)
这是非常错误的。如果你坚持不使用strcpy
做这样的事情(未经测试)
int iStringLength = strlen(name);
for (i = 0; i < iStringLength; i++) {
s->name[i] = name[i];
}
但要确保长度不超过数组大小。
这也是错误的
Student* makeAndrew(void) {
Student s;
setName(&s, "Andrew");
setStudentID(&s, 12345678);
return &s;
}
因为s
对象在函数退出时被销毁 - 它是函数作用域的本地对象,但是你返回一个指向它的指针。因此,如果您尝试使用此指针访问结构,则它将无效,因为实例不再存在。如果您想这样做,您应该使用malloc
动态分配它。或者,根本不要返回指针,并使用@Andrew的替代选项。
答案 1 :(得分:2)
在“另一种方法”中,您在本地声明Student s
,它将动态分配空间(通常在堆栈上),并在完成时返回该地址。
然而,该堆栈空间将在返回时被释放,因此无法保证数据未被破坏 - 实际上它可能就是它!
在对方法的调用中声明Student s
,并将指针传递给makeAndrew:
void makeAndrew(Student *s) {
setName( s, "Andrew");
setStudentID( s, 12345678);
}
...
Student s;
makeAndrew( &s );
...
答案 2 :(得分:0)
您的函数makeAndrew
返回指向局部变量的指针。它仅在作用域结束之前有效,因此一旦函数完成,它将在内存被覆盖时改变 - i。即几乎是瞬间。你必须动态地分配它(使用Student *s = new Student;
,或者如果你真的想坚持使用纯C,Student *s = malloc (sizeof Student );
,然后在不需要它以避免内存泄漏之后将其释放到函数之外。 / p>
或者像安德鲁建议的那样,它不那么容易出错。
答案 3 :(得分:0)
我会将makeAndrew()函数更改为只返回一个结构,而不是指向结构的指针,以便在返回指向临时变量的指针时更正错误:
Student makeAndrew(void)
{
Student s;
setName(&s, "Andrew");
setStudentID(&s, 12345678);
return s;
}
Student aStudent = makeAndrew();
你的setName确实有一个关于temp的错误,它应该是一个char *,因为你在循环中递增它以指向输入c-string中的另一个字符。我认为它也错过了空终止。正如您在评论中提到的那样,应该检查Student中名称char数组的溢出:
void setName(Student* s, const char* name) { // 's' is a pointer to a Student struct |
// 'name' is a pointer to the first element of a char array (repres. a string)
const char *temp;
int i;
for (i = 0, temp = name; *temp != '\0' && i <= MAX_NAME_LEN; temp++, i++)
{
*((s->name) + i) = *temp;
}
s->name[i] = '\0';
}
您可以使用strncpy来简化setName:
void setName2(Student *s,const char *name)
{
#include <string.h>
strncpy(s->name, name,MAX_NAME_LEN);
s->name[MAX_NAME_LEN] = '\0';
}