我意识到在函数调用中声明的变量被压入堆栈,一旦函数到达它的末尾,声明到堆栈上的局部变量就会弹出并进入lala land。
我不承认的是,如果我在函数中声明一个指针,我可以返回没有编译器投诉的指针,而对于数组,它会给我一个警告。
以下是我所指的一个例子:
char * getStringArray();
char * getStringPointer();
int main(){
char * temp1 = getStringPointer();
char * temp2 = getStringArray();
return 0;
}
char * getStringPointer(){
char * retString = "Fred";
return retString;
}
char * getStringArray(){
char retString[5] = {'F', 'r','e','d','\0'};
return retString;
}
在编译期间,它会抛出一个关于getStringArray()的“返回本地变量的地址”警告。令我困惑的是,我被告知仅仅通过名称引用数组(如retString,no [])引用它在内存中的地址,就像指针一样。
数组可以很方便,有很多次我想在函数中使用数组并返回它,有没有快速解决这个问题?
正如我在评论中提到的,这会有效吗?我猜测malloc分配给堆但是很好。我仍然不清楚静态数据和堆上数据之间的区别。
char * getStringPointer(){
char * retString = (char *)malloc(sizeof(char)*4+1);
*(retString+0) = 'F';
*(retString+1) = 'r';
*(retString+2) = 'e';
*(retString+3) = 'd';
*(retString+4) = '\0';
return retString;
}
答案 0 :(得分:3)
"Fred"
是一个未命名的全局,因此它不会消失,返回指向它的指针是安全的。但getStringArray()
正在取消分配指针指向的所有内容。这就是区别。
答案 1 :(得分:3)
getStringPointer
在堆栈上分配一个指针,然后返回指针,指向可执行文件中某个字符串'Fred \ 0'(不在堆栈中)。
getStringArray
在堆栈上为5个字符分配空间,将它们分配给'F''r''e''d'和'\ 0',然后返回一个指向'F'地址的指针,该地址位于堆栈(因此在函数返回后无效)。
有两种方法围绕它:要么你可以malloc
堆上你的数组的一些空间,要么你可以创建一个包含适当大小的数组的struct
并返回它。您可以从函数返回数值,指针和结构类型,但不能返回数组。
答案 2 :(得分:0)
数组明确地是指向堆栈本地内存的指针,因此编译器确定您正在泄漏的内容,这就是您收到警告的原因。
只需创建数组static
,警告和生命周期限制都将消失。
现在,指针可能指向静态或堆中的东西(在你的情况下它实际上是静态的),所以从一个表达式中查看你是否正在泄漏某些堆栈本地或不是这一点并不明显。这就是你返回指针时没有得到警告的原因,无论它是否安全返回。同样,static
存储类将为您节省开支。你的字符串常量恰好是静态的,所以工作正常。
答案 3 :(得分:0)
通过向变量static
添加retString
修饰符并返回指针将解决问题。
char * getStringArray(){
static char retString[5] = {'F', 'r','e','d','\0'};
return retString;
}
这将返回适当的值。
注意它仍被视为指针,因为数组的第一个元素被衰减为类型为T的指针,在本例中为char
。这将使编译器感到高兴,因为它匹配在源的开头定义的函数本身的原型声明。