C 堆栈存储器基础

C 堆栈存储器基础,c,stack,C,Stack,考虑以下代码: char* foo(int myNum) { char* StrArray[5] = {"TEST","ABC","XYZ","AA","BB"}; return StrArray[4]; } 当我将StrArray[4]返回给调用者时,这应该有效吗? 由于数组是在堆栈上定义的,当调用方获取指针时,该部分内存已超出范围。或者这个代码可以工作吗 此代码将起作用。您正在StrArray[4]中返回指针的值,它指向一个常量字符串“BB”。常量字符串的生存期等于整

考虑以下代码:

 char* foo(int myNum) {
    char* StrArray[5] = {"TEST","ABC","XYZ","AA","BB"};

    return StrArray[4];
 }
当我将
StrArray[4]
返回给调用者时,这应该有效吗?
由于数组是在堆栈上定义的,当调用方获取指针时,该部分内存已超出范围。或者这个代码可以工作吗

此代码将起作用。您正在
StrArray[4]
中返回指针的值,它指向一个常量字符串
“BB”
。常量字符串的生存期等于整个程序的生存期

重要的是指针指向的对象的生存期,而不是指针存储的位置。例如,以下类似代码将不起作用:


这是因为
bb
数组是
foo()
函数堆栈上的一个临时值,返回时会消失。

C使用标记从0开始的数组。所以第一个元素是StrArray[0]

因此StrArray[5]没有在代码中声明


C将允许您编写代码以返回StrArray[5],但wht未定义,在操作系统和编译器上会有所不同,但通常会使程序崩溃。

代码可以工作。您返回的点(
StrArray[4]
)指向字符串文本
“BB”
。C中的字符串文字是具有静态存储持续时间的匿名数组对象,这意味着它们的寿命与程序的寿命一样长(即永远)。无论你在哪里创造出这样的文字都无关紧要。即使它被引入函数中,它仍然具有静态存储持续时间


请记住,字符串文字是不可修改的,因此最好使用带有字符串文字的
const char*
指针。

小心:你在对编译器撒谎

StrArray
的每个元素都指向一个只读
char*

您告诉编译器函数的返回值是可修改的
char*

对编译器撒谎,它迟早会报仇的

在C语言中,声明指向只读数据的指针的方法是用
const
限定它

我将您的代码编写为:

const char* foo(int myNum) {
   const char* StrArray[5] = {"TEST","ABC","XYZ","AA","BB"};

   return StrArray[4];
}

堆栈上只有指针数组,而不是字符串文字常量。

我认为应该是“当我返回StrArray[4]…”嗯,这取决于-可能是OP意味着StrArray[5]它与您的问题无关,但在本例中,您没有使用传递给foo的myNum参数。这是可行的,但我建议不要这样做。在其他地方定义常量。虽然,这取决于您的情况,但可能有一段时间这是一个不错的设计。仔细想想,它不是在字符数组中返回char*,StrArray[4]吗?如果我错了,请纠正我。@Amit:你错了,原来的问题是返回一个指向StrArray[4]指向的任何对象的指针,即“BB”。@Greg:谢谢,我理解你给出的解释。另外需要注意的是,在C中,字符串文字具有静态存储持续时间(它将一直存在到应用程序结束…)。数组在函数作用域的末尾消失了-但是字符串文字不是一个强制性的迂腐注释:):
bb
在聚合初始值设定项中只允许在C99中使用,而在C89/90中不允许。后者只允许在聚合初始值设定项中使用常量表达式,而上面的
bb
则不允许。在该特定示例中,您甚至可以更进一步,使其
const char*const StrArray[5]={/*which*/}:))
const char* foo(int myNum) {
   const char* StrArray[5] = {"TEST","ABC","XYZ","AA","BB"};

   return StrArray[4];
}