1

所以我现在正在尝试学习 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 实施不正确。

任何指针?(没有双关语)

4

4 回答 4

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 的替代选项。

于 2012-09-09T10:52:53.710 回答
2

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

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

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

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


...

Student s;
makeAndrew( &s );

...
于 2012-09-09T10:52:42.523 回答
0

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

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

于 2012-09-09T10:56:40.783 回答
0

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

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

Student aStudent = makeAndrew();

您的 setName 确实有关于 temp 的错误,它应该是一个 char *,因为您在循环中递增它以指向输入 c 字符串中的另一个字符。我认为它也缺少空终止。正如您在评论中提到的那样,应该检查学生中名称字符数组的溢出:

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';
}
于 2012-09-09T14:58:13.843 回答