1

我应该遵循以下标准:

实现函数 answer4(指针参数和 n):

  1. malloc()使用n 个项目 准备一个 student_record 数组。

  2. 将参数中的学生记录复制到数组 n 次。

  3. 返回数组。

我提供了下面的代码,但这显然是不正确的。实现这一点的正确方法是什么?

student_record *answer4(student_record* p, unsigned int n)
{
    int i;
    student_record* q = malloc(sizeof(student_record)*n);
    for(i = 0; i < n ; i++){
        q[i] = p[i];
    }
    free(q);
    return q;
};
4

8 回答 8

1
p = malloc(sizeof(student_record)*n);

这是有问题的:您正在覆盖p输入参数,因此您无法引用在该行之后传递的数据。

这意味着您的内部循环读取初始化数据。

这:

return a; 

也是有问题的——它会返回一个指向局部变量的指针,这不好——一旦函数返回,指针就会变得无效。

你需要的是这样的:

student_record* ret = malloc(...);

for (int i=...) {
 // copy p[i] to ret[i]
}

return ret;
于 2012-04-27T15:02:04.843 回答
1

1)您通过调用重新分配了 p,即您应该复制的数组malloc()

2)您不能返回本地堆栈变量(a)的地址。将 a 更改为指针,将其 malloc 为 p 的大小,然后将 p 复制到其中。Malloc 的内存是内存,因此您可以返回这样的地址。

于 2012-04-27T15:02:46.573 回答
1

a[]是一个本地自动数组。一旦你从函数返回,它就会从内存中删除,所以调用函数不能使用你返回的数组。

您可能想要做的是malloc一个新数组(即 not p),您应该将重复项分配到其中并返回其值而不释放分配的内存。

于 2012-04-27T15:03:36.210 回答
1

尝试使用更好的名称,这可能有助于避免代码中出现明显的混淆错误。

例如,使用以下命令启动函数:

student_record * answer4(const student_record *template, size_t n)
{
...
}

它还使代码更清晰。请注意,我添加const是为了更清楚地说明第一个参数是仅输入的,并制作了第二个参数的类型,size_t这在处理“计数”和事物的大小时很好。

于 2012-04-27T15:03:56.087 回答
1

这个问题中的代码发展得很快,但在给出这个答案时它包含以下两行:

free(q);
return q;

这肯定是错误的——在free对其参数的调用指向无效内存之后,使用q. 即你返回一个无效的指针。既然你要回来q了,不要释放它!它成为“调用者拥有的”变量,并成为调用者释放它的责任。

于 2012-04-27T15:25:33.000 回答
0
student_record* answer4(student_record* p, unsigned int n)
{
    uint8_t *data, *pos;
    size_t size = sizeof(student_record);
    data = malloc(size*n);

    pos = data;
    for(unsigned int i = 0; i < n ; i++, pos=&pos[size])
        memcpy(pos,p,size);

    return (student_record *)data;
};

你可以这样做。

于 2012-04-27T15:10:23.780 回答
0

这编译,我认为,做你想要的:

student_record *answer4(const student_record *const p, const unsigned int n)
{
    unsigned int i;
    student_record *const a = malloc(sizeof(student_record)*n);
    for(i = 0; i < n; ++i)
    {
        a[i] = p[i];
    }
    return a;
};

几点:

  1. 现有数组被标识为p。你想从中复制。您可能不想释放它(释放它可能是调用者的工作)。
  2. 新数组是a。你想复制到它。该函数无法释放它,因为调用者将需要它。因此,调用者必须负责释放它,一旦调用者完成了它。
  3. 该数组有n元素,索引从 0 到 n-1。因此,表示索引上限的常用方法是i < n.
  4. const我添加的s 不是必需的,但编写良好的代码可能会包含它们。
于 2012-04-27T15:13:03.570 回答
0

Altought,这个问题以前有很好的答案,我不能避免添加我自己的。因为我在 Collegue 学过 pascal 编程,所以我习惯这样做,用 C 相关的编程语言:

void* AnyFunction(int AnyParameter)
{
   void* Result = NULL;

   DoSomethingWith(Result);

   return Result;
}

这有助于我轻松调试,并避免像 @ysap 提到的与指针相关的错误。

需要记住的重要一点是,问题提到要返回一个 SINGLE 指针,这是一个常见的警告,因为指针可以用于处理单个项目或连续数组!

这个问题建议使用数组作为一个概念,带有指针,而不是使用数组语法。

// returns a single pointer to an array:
student_record* answer4(student_record* student, unsigned int n)
{
  // empty result variable for this function:
  student_record* Result = NULL;

  // the result will allocate a conceptual array, even if it is a single pointer:
  student_record* Result = malloc(sizeof(student_record)*n);

  // a copy of the destination result, will move for each item
  student_record* dest = Result;

  int i;
  for(i = 0; i < n ; i++){
    // copy contents, not address:
    *dest = *student;

    // move to next item of "Result"
    dest++;
  }

  // the data referenced by "Result", was changed using "dest"
  return Result;
} // student_record* answer4(...)

检查一下,这里没有下标运算符,因为使用指针寻址。

请不要开始帕斯卡与 c 的火焰战争,这只是一个建议。

于 2012-04-27T15:36:34.983 回答