C使用malloc和复制数组

时间:2012-04-27 14:56:23

标签: c

我应该遵循以下标准:

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

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

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

  3. 返回数组。

  4. 我带了下面的代码,但显然不正确。实现这个的正确方法是什么?

    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;
    };
    

8 个答案:

答案 0 :(得分: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;

答案 1 :(得分:1)

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

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

答案 2 :(得分:1)

a[]是一个本地自动数组。从函数返回后,它将从内存中删除,因此调用函数无法使用您返回的数组。

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

答案 3 :(得分:1)

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

例如,使用以下命令启动该功能:

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

它还使代码更清晰。请注意,我添加const以更清楚地表明第一个参数是仅输入的,并且使第二个size_t的类型在处理“计数”和事物大小时很好。< / p>

答案 4 :(得分:1)

这个问题中的代码发展得非常快,但在回答这个问题时,它包含以下两行:

free(q);
return q;

这保证是错误的 - 在调用free之后,它的参数指向无效的内存,随后在使用q的值时可能发生任何事情。即你返回一个无效的指针。由于您正在返回q,请不要将其释放!它成为一个“来电者拥有”的变量,它成为了呼叫者释放它的责任。

答案 5 :(得分: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;
};

你可能会喜欢这样。

答案 6 :(得分: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不是必需的,但编写良好的代码可能会包含它们。

答案 7 :(得分:0)

Altought,此问题之前有好的答案,我无法避免添加自己的答案。由于我在Collegue中获得了pascal编程,我习惯于用C相关的编程语言来做这个:

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

   DoSomethingWith(Result);

   return Result;
}

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

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

这个问题建议使用数组作为A CONCEPT,带指针,不使用ARRAY SYNTAX。

// 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(...)

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

请不要启动pascal v.s. c火焰战,这只是一个建议。