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

返回函数中声明的数组返回C中局部变量的地址?,c,arrays,pointers,C,Arrays,Pointers,我意识到在函数调用中声明的变量被推到堆栈上,一旦函数到达其末端,声明到堆栈上的局部变量就会弹出并进入拉拉区 我不明白的是,如果我在一个函数中声明一个指针,我可以返回这个指针,而没有编译器的抱怨,而对于一个数组,它确实会给我一个警告 下面是我指的一个例子: char * getStringArray(); char * getStringPointer(); int main(){ char * temp1 = getStringPointer(); char *

我意识到在函数调用中声明的变量被推到堆栈上,一旦函数到达其末端,声明到堆栈上的局部变量就会弹出并进入拉拉区

我不明白的是,如果我在一个函数中声明一个指针,我可以返回这个指针,而没有编译器的抱怨,而对于一个数组,它确实会给我一个警告

下面是我指的一个例子:

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分配给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”
是一个未命名的全局变量,因此它不会消失,返回指向它的指针是安全的。但是
getStringArray()
正在取消分配指针指向的所有内容。这就是区别。

“Fred”
是一个未命名的全局变量,因此它不会消失,返回指向它的指针是安全的。但是
getStringArray()
正在取消分配指针指向的所有内容。这就是不同之处。

getStringPointer
在堆栈上分配一个指针,然后返回该指针,该指针指向可执行文件中某个地方(而不是堆栈上)的字符串“Fred\0”。
getStringArray
为堆栈上的5个字符分配空间,为它们分配“F”“r”“e”“d”和“\0”,然后返回指向堆栈上“F”地址的指针(因此在函数返回后无效)


有两种方法可以解决这个问题:要么你可以
malloc
在堆上为你的数组留出一些空间,要么你可以创建一个
struct
,其中包含一个大小合适的数组并返回它。您可以从函数返回数字、指针和结构类型,但不能从数组返回。getStringPointer正在堆栈上分配指针,然后返回该指针,该指针指向可执行文件(不在堆栈上)某处的字符串“Fred\0”。
getStringArray
为堆栈上的5个字符分配空间,为它们分配“F”“r”“e”“d”和“\0”,然后返回指向堆栈上“F”地址的指针(因此在函数返回后无效)


有两种方法可以解决这个问题:要么你可以
malloc
在堆上为你的数组留出一些空间,要么你可以创建一个
struct
,其中包含一个大小合适的数组并返回它。您可以从函数返回数字、指针和结构类型,但不能从数组返回。

数组无疑是指向堆栈本地内存的指针,因此编译器确定这就是您泄漏的内容,因此您会收到警告

只要将数组设置为静态,警告和生存期限制都将消失


现在,指针可能指向某个静态的或堆中的内容(在您的例子中,它实际上是静态的),因此,仅从一个表达式来看,您是否泄漏了堆栈本地内容并不明显。这就是为什么无论返回指针是否安全,返回指针时都不会收到警告。同样,
静态
存储类将为您节省时间。字符串常量恰好是静态的,因此可以正常工作。

数组无疑是指向堆栈本地内存的指针,因此编译器确定这就是您泄漏的内容,这就是您收到警告的原因

只要将数组设置为静态,警告和生存期限制都将消失


现在,指针可能指向某个静态的或堆中的内容(在您的例子中,它实际上是静态的),因此,仅从一个表达式来看,您是否泄漏了堆栈本地内容并不明显。这就是为什么无论返回指针是否安全,返回指针时都不会收到警告。同样,
静态
存储类将为您节省时间。字符串常量恰好是静态的,因此可以正常工作。

通过向变量
retString
添加
static
修饰符并返回指针,可以解决此问题

char * getStringArray(){
        static char retString[5] = {'F', 'r','e','d','\0'};
        return retString;
}
这将返回适当的值

请注意,它仍然被视为指针,因为数组的第一个元素已衰减为T类型的指针,在本例中为
char
。这将使编译器感到高兴,因为它与源代码开头定义的函数本身的原型声明相匹配


请参见

,在变量
retString
中添加一个
static
修饰符并返回指针将解决此问题

char * getStringArray(){
        static char retString[5] = {'F', 'r','e','d','\0'};
        return retString;
}
这将返回适当的值

请注意,它仍然被视为指针,因为数组的第一个元素已衰减为T类型的指针,在本例中为
char
。这将使编译器感到高兴,因为它与源代码开头定义的函数本身的原型声明相匹配


参见

什么是拉拉土地?指针只是指向内存中地址的指针。关于
getStringArray()
会引发什么警告,这并不奇怪,您已经声明并定义了一个包含五个字符的数组,并将其返回,但是该定义与声明并定义为指向字符指针的原型不匹配。@t0mm13b一个
char
数组衰减为指向
char
的指针。因此,就语言律师而言,
getStringArray
并没有违法之处。当然是波因