简体   繁体   English

在函数中声明的返回数组返回C中局部变量的地址?

[英]Returning array declared in function returns address of local variable in C?

I realize that variables declared in a function call are pushed onto the stack and once the function reaches its end the local variables declared onto the stack are popped off and go into lala land. 我意识到,在函数调用中声明的变量将被压入堆栈,并且一旦函数到达其末尾,就会弹出声明在堆栈上的局部变量并进入lala领域。

The thing I don't undertstand is that if I declare a pointer in a function I can return the pointer with no compiler complaint, whereas with an array it does give me a warning. 我不了解的是,如果我在函数中声明了指针,则可以返回该指针而无需编译器投诉,而对于数组,它确实会警告我。

Here is an example of what I'm referring to: 这是我所指的示例:

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

During compilation it throws a "returning address of local variable" warning about getStringArray(). 在编译期间,它将引发有关getStringArray()的“局部变量的返回地址”警告。 What confuses me is that I've been told that referencing an array solely by its name(like retString, no[])refers to its address in memory, acting like a pointer. 令我感到困惑的是,有人告诉我,仅通过名称来引用数组(例如retString,no [])是指其在内存中的地址,就像指针一样。

Arrays can be handy and there are many times I would like to use an array in a function and return it, is there any quick way around this? 数组可以派上用场,很多时候我想在函数中使用数组并返回它,有什么快速的方法吗?

As I referred to in a comment, will this work? 正如我在评论中提到的那样,这行得通吗? I'm guessing malloc allocates to heap but so its fine. 我猜malloc分配给堆,但它很好。 I'm still a little unclear of the difference between static data and data on the heap. 我仍然不清楚静态数据和堆上的数据之间的区别。

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

"Fred" is an unnamed global, so it's not going away, and returning a pointer to it is safe. "Fred"是一个未命名的全局变量,因此不会消失,并且返回指向它的指针是安全的。 But getStringArray() is de-allocating everything that pointer points to. 但是getStringArray()正在取消分配指针指向的所有内容。 That's the difference. 就是这样。

getStringPointer is allocating a pointer on the stack, then returning that pointer, which points to the string 'Fred\\0' somewhere in your executable (not on the stack). getStringPointer在堆栈上分配一个指针,然后返回该指针,该指针指向可执行文件中某个位置的字符串“ Fred \\ 0”(不在堆栈上)。 getStringArray allocates space for 5 chars on the stack, assigns them 'F' 'r' 'e' 'd' and '\\0', then returns a pointer to the address of 'F', which is on the stack (and therefore invalid after the function returns). getStringArray为堆栈上的5个字符分配空间,将它们分配为'F''r''e''d'和'\\ 0',然后返回指向堆栈上的'F'地址的指针(因此函数返回后无效)。

There are two ways round it: either you can malloc some space for your array on the heap, or you can make a struct that contains an appropriately sized array and return that. 有两种方法围着它,要么你可以malloc为您的阵列一些空间上的堆,或者你可以做一个struct ,它包含一个适当大小的数组并返回。 You can return numerical, pointer and struct types from functions, but not arrays. 您可以从函数中返回数值,指针和结构类型,但不能返回数组。

The array is unambiguously a pointer to stack-local memory so the compiler is certain that's what you are leaking, so that's why you get the warning. 该数组无疑是指向堆栈本地内存的指针,因此编译器可以确定这就是您要泄漏的内容,因此这就是您收到警告的原因。

Just make the array static and both the warning and the lifetime restriction will vanish. 只需将数组设置为static ,警告和生存期限制都将消失。

Now, the pointer could be pointing to something static or in the heap (in your case it actually was static) and so it's not obvious from looking at just that one expression whether you are leaking something stack-local or not. 现在,该指针可能指向静态对象或堆中的对象(在您的情况下,它实际上是静态的),因此从仅查看一个表达式(无论您是否泄漏本地堆栈)并不明显。 That's why you don't get the warning when you return a pointer, regardless of whether it's a safe return or not. 这就是为什么无论返回安全指针如何都不会返回警告的原因。 Again, the static storage class will save you. 同样, static存储类将保存您。 Your string constant happens to be static, so that works fine. 您的字符串常量恰好是静态的,因此可以正常工作。

By adding a static modifier to the variable retString and returning back a pointer will resolve the issue. 通过将static修饰符添加到变量retString并返回指针将解决此问题。

char * getStringArray(){
        static char retString[5] = {'F', 'r','e','d','\0'};
        return retString;
}

That will return the appropriate value. 那将返回适当的值。

Notice how its still treated as a pointer, because the first element of the array is decayed into a pointer of type T, in this case, char . 请注意,它仍然如何被当作指针,因为数组的第一个元素被衰减为T类型的指针,在这种情况下为char This will make the compiler happy as it matches the prototype declaration of the function itself as defined at the start of the source. 这将使编译器感到满意,因为它与在源开始处定义的函数本身的原型声明相匹配。

See ideone sample ideone样品

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM