动态分配内存有四种方法,这四种方式有区别吗? 首先是这样的:
char *seq=(char *)malloc(100*sizeof(char));
void exam(char *seq){
// using 'seq'
}
第二个像这样:
char *seq;
void exam(char *seq){
seq=(char *)malloc(100*sizeof(char));
// using 'seq'
}
第三个像这样:
char *seq=(char *)malloc(10*sizeof(char));
void exam(char *seq){
char *change=(char *)malloc(100*sizeof(char));
free(seq);
seq=change;
// using 'seq'
}
第四个像这样:
char *seq=(char *)malloc(100*sizeof(char));
void exam(char *seq){
free(seq);
seq=(char *)malloc(100*sizeof(char));
//using 'seq'
}
你应该知道,我会在方法'考试'之外使用变量'seq'。 请解释上述代码,非常感谢。
答案 0 :(得分:2)
如果您打算在考试之外使用seq,则只有第一种情况有效。
其他三种情况接收为seq分配的地址,但无法更改。
要更改seq的值,您需要为其返回一个新值,或者显式修改seq中的内容。
您需要调查Pass by Value以了解为什么这不起作用。请参阅this page。
答案 1 :(得分:1)
这一切都取决于你想要做什么。如果可能的话,最好在相同的范围内进行malloc / free,IMO,它使代码更具可读性 - C中的内存分配已经足够困难了。在您的情况下,您将首先malloc,调用该函数,并在函数外部释放。但当然,并非总是可行。
你的一些解决方案不起作用:例如,第二个解决方案不会做你想要的,因为当你调用函数时,指针被复制:
char *p;
function(p);
void function(char *q) {
// q is a copy of p, so when q is set by malloc, it will not be reflected in p
q = malloc(100);
}
通常,你应该做fopen函数:你返回一个指针:
char* p function() {
char* ret;
ret = malloc(100);
return ret;
}
char *p = function();
或者您可以使用指向指针的指针:
char *p;
function(&p);
void function(char **q) {
// q is a copy of &p, so when *q is set by malloc, it is the same memory location as &p
*q = malloc(100);
}
我认为第一个一般情况要好得多。
另外,关于你的风格:sizeof(char)是无用的,无论你使用什么编译器/平台,它总是等于1,并且转换malloc是无用的并且实际上是危险的(因为它隐藏了缺少的头部包含在哪里malloc被声明)。只有在C ++中使用malloc时才有用(强制转换为强制转换)。
答案 2 :(得分:1)
可能有很多方法可以做你做的事情。如果您打算在函数外部使用seq,那么您概述的第一种方法将起作用。
如果您打算在调用函数后使用seq,那么其他方法还有其他问题。由于C是按值传递的,因此您将seq中包含的地址传递给例程,该例程不会更改最后三个示例中与seq关联的内存位置。要更改seq的内存位置,需要将指针的地址传递给例程以设置指针。这在David Cournapeau的例子中有所体现。
最后两种情况的问题是你“释放”了内存,但你仍然保留了一个指向内存的指针,因为seq的值不会被改变,你可以使用它来访问你已经“释放”的内存”。这是一个悬垂的指针。
David Cournapeau建议使用函数返回指针,这样您就可以访问在函数中分配的内存。否则,您需要将seq的地址传递给例程,并取消引用该值以将其设置为已分配的空间。
答案 3 :(得分:1)
你不应该转换malloc()的结果,除非你使用的是早于1989 ANSI标准的C实现,或者你打算用C ++编译这个代码,在这种情况下你应该使用new而不是malloc ();首先,它没有必要,其次,如果你没有范围内的malloc()原型,它将掩盖编译器诊断。
另外,sizeof(char)的定义是1;在这种情况下使用它没有任何区别,只是增加了视觉噪音。
为任何类型T编写malloc()语句的规范形式是
T *p = malloc(count * sizeof *p);
或
T *p;
...
p = malloc(count * sizeof *p);
现在处理你的四个案件......
你的第一个案件通常是正确的;你在考试之外为seq分配内存,并按值传递指针。
你剩下的案件都有类似的问题;对指针值seq的更改不会反映在调用者中,并且您将引入内存泄漏。如果您正在传递指向函数的指针,并且希望覆盖指针值,则需要将指针传递给该指针:
char *seq;
exam(&seq);
...
void exam(char **seq) { *seq = malloc(100); ... }
如果要调整动态分配的缓冲区的大小,请使用realloc():
char *seq = malloc(10);
exam(&seq);
...
void exam(char **seq)
{
char *tmp = realloc(*seq, 100);
if (!tmp)
{
/* realloc failed */
}
else
{
*seq = tmp;
...
}
请注意
char *p = realloc(NULL, 10);
与
相同char *p = malloc(10);
答案 4 :(得分:0)
我认为这些是范围上的差异
答案 5 :(得分:0)
要了解情况,请考虑重写:
char *seq=(char *)malloc(100*sizeof(char));
void exam(char *var){
// using 'var'
}
//--
char *seq;
void exam(char *var){
var=(char *)malloc(100*sizeof(char));
// using 'var'
}
//--
char *seq=(char *)malloc(10*sizeof(char));
void exam(char *var){
char *change=(char *)malloc(100*sizeof(char));
free(var);
var=change;
// using 'var'
}
//--
char *seq=(char *)malloc(100*sizeof(char));
void exam(char *var){
free(var);
var=(char *)malloc(100*sizeof(char));
//using 'var'
}
致电时
exam(seq);
以上版本与原版相同。