我应该遵循以下标准:
实现函数answer4(指针参数和n):
使用malloc()
个n项准备一个student_record数组。
将学生记录从参数复制到数组n 次。
返回数组。
我带了下面的代码,但显然不正确。实现这个的正确方法是什么?
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;
};
答案 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;
};
有几点:
p
。你想从中复制。你可能不想释放它(释放它可能是调用者的工作)。a
。你想复制到它。该函数无法释放它,因为调用者需要它。因此,一旦呼叫者完成了呼叫,呼叫者必须负责释放它。n
个元素,索引为0到n-1。因此,表达索引上限的常用方法是i < n
。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火焰战,这只是一个建议。