C——结构和指针基本问题

C——结构和指针基本问题,c,struct,C,Struct,所以我现在正试图学习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 cha

所以我现在正试图学习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;
}
我肯定在某种程度上是错的。。。我还认为我的setName实现不正确

有什么建议吗?(没有双关语)

在您的“另一种方法”中,您在本地声明
学生s
,该方法将动态分配空间(通常在堆栈上),并在完成时返回该地址

但是,该堆栈空间将在返回时释放,因此不能保证数据不会被破坏——事实上,很可能是这样的

在调用方法时声明
Student s
并将指针传递给make安德鲁:

void makeAndrew(Student *s) {
    setName( s, "Andrew");
    setStudentID( s, 12345678);
}


...

Student s;
makeAndrew( &s );

...
在“另一个方法”中,您在本地声明
Student s
,该方法将动态分配空间(通常在堆栈上),并在完成时返回该地址

但是,该堆栈空间将在返回时释放,因此不能保证数据不会被破坏——事实上,很可能是这样的

在方法调用中声明
Student s
,并将指针传递给makeAndrew:

void makeAndrew(Student *s) {
    setName( s, "Andrew");
    setStudentID( s, 12345678);
}


...

Student s;
makeAndrew( &s );

...

这是非常错误的。如果您坚持不使用strcpy,请执行类似操作(未测试)


因为
s
对象在函数退出时被销毁-它是函数作用域的本地对象,但您返回指向它的指针。因此,如果尝试使用此指针访问结构,它将无效,因为实例已不存在。如果您想这样做,您应该使用
malloc
动态分配它。或者根本不返回指针,使用@Andrew的替代选项。

这是非常错误的。如果您坚持不使用strcpy,请执行类似操作(未测试)


因为
s
对象在函数退出时被销毁-它是函数作用域的本地对象,但您返回指向它的指针。因此,如果尝试使用此指针访问结构,它将无效,因为实例已不存在。如果您想这样做,您应该使用
malloc
动态分配它。或者根本不返回指针,使用@Andrew的可选选项。

您的函数
makeAndrew
返回指向局部变量的指针。它只在作用域结束之前有效,因此一旦函数完成,它将在内存被覆盖时更改-i。E几乎立刻。您必须动态地分配它(使用
Student*s=new Student;
,或者如果您真的想坚持使用纯C,
Student*s=malloc(sizeof Student);
,然后在不需要时将其释放到函数外部以避免内存泄漏


或者按照Andrew的建议去做,这样更不容易出错。

你的函数
makeAndrew
返回指向一个局部变量的指针。它只在作用域结束之前有效,所以一旦函数完成,当内存被覆盖时,它就会改变——即几乎是立即改变。你必须动态地分配它(使用
Student*s=new Student;
,或者如果您真的想使用纯C,
Student*s=malloc(sizeof Student);
,然后在不需要时将其释放到函数外部以避免内存泄漏


或者按照Andrew的建议去做,这样更不容易出错。

我会将makeAndrew()函数改为只返回一个结构,而不是指向一个结构的指针,以更正关于返回指向临时变量的指针的错误:

Student makeAndrew(void) 
{
    Student s;
    setName(&s, "Andrew");
    setStudentID(&s, 12345678);
    return s;
}

Student aStudent = makeAndrew();
您的setName确实存在与temp相关的错误,temp应该是char*,因为您正在循环中递增它以指向输入c字符串中的另一个字符。我认为它也缺少空终止符。正如您在注释中提到的,应该检查Student中的name 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';
}
void setName(Student*s,const char*name){/'s'是指向Student结构的指针|
//“name”是指向char数组(代表字符串)的第一个元素的指针
常量字符*温度;
int i;
对于(i=0,temp=name;*temp!='\0'和&i 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';
}
void setName2(学生*s,常量字符*name)
{
#包括
strncpy(s->name,name,MAX\u name\u LEN);
s->name[MAX_name_LEN]='\0';
}

我会将makeAndrew()函数更改为只返回结构,而不是指向结构的指针,以更正有关返回指向临时变量的指针的错误:

Student makeAndrew(void) 
{
    Student s;
    setName(&s, "Andrew");
    setStudentID(&s, 12345678);
    return s;
}

Student aStudent = makeAndrew();
您的setName确实存在与temp相关的错误,temp应该是char*,因为您正在循环中递增它以指向输入c字符串中的另一个字符。我认为它也缺少空终止符。正如您在注释中提到的,应该检查Student中的name 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';
}
void setName(Student*s,const char*name){/'s'是指向Student结构的指针|
//“name”是指向char数组(代表字符串)的第一个元素的指针
常量字符*温度;
int i;
对于(i=0,temp=name;*temp!='\0'和&i 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';
}
void setName2(学生*s,常量字符*name)
{
#包括
strncpy(s->name,name,MAX\u name\u LEN);
s->name[MAX_name_LEN]='\0';
}

不要手动复制,使用例如
strcpy
setName
不检查输入字符串的长度,因此它可能会在足够长的输入字符串中崩溃。您需要
temp!='\0'&&i
for
循环中使用例如
strcpy
setName
进行手动复制不要检查输入字符串的长度,因此如果输入字符串足够长,它可能会崩溃。您需要
te