【问题标题】:Stack memory fundamentals堆栈内存基础
【发布时间】:2010-12-14 18:00:06
【问题描述】:

考虑这段代码:

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

    return StrArray[4];
 }

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

【问题讨论】:

  • 我认为应该是“当我返回 StrArray[4] ..”
  • 嗯取决于 - 它可能是 OP 的意思 StrArray[5]
  • 这与您的问题无关,但在示例中您没有使用传递给 foo 的 myNum 参数。
  • 这可行,但我建议不要这样做。在其他地方定义你的常量。虽然,这取决于您的情况,但有时这可能是一个不错的设计。稍微考虑一下。

标签: c stack


【解决方案1】:

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

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

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

   return StrArray[4];
}

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

【讨论】:

  • 不是将 char * 返回到字符数组 StrArray[4] 吗?纠正我,如果我错了。
  • @Amit:你错了,原来的问题是返回一个指向 StrArray[4] 指向的指针,即“BB”。
  • @Greg:谢谢,你的解释我明白了。
  • 作为附加说明 - 在 C 中,字符串文字具有静态存储持续时间(它将一直存在到应用程序结束......)。数组在这里函数范围的末尾消失了 - 但字符串文字不是
  • 一个强制性的迂腐评论 :) : bb 在聚合初始化器中只允许在 C99 中,但在 C89/90 中不允许。后者只允许在聚合初始化器中使用常量表达式,而上面的bb 不允许。
【解决方案2】:

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

因此,您的代码中没有声明 StrArray[5]。

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

【讨论】:

    【解决方案3】:

    代码将起作用。您返回的点 (StrArray[4]) 指向字符串文字 "BB"。 C 中的字符串文字是具有静态存储持续时间的匿名数组对象,这意味着它们的存在时间与您的程序存在的时间一样长(即永远存在)。在哪里创建该刺痛文字并不重要。即使在函数内部引入,它仍然具有静态存储时长。

    请记住,字符串文字不可修改,因此最好将const char* 指针与字符串文字一起使用。

    【讨论】:

      【解决方案4】:

      当心:你在对编译器撒谎。

      StrArray 的每个元素都指向一个只读的char *
      你告诉编译器你的函数的返回值是一个 modifiable char *
      对编译器撒谎,迟早会报仇的。

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

      我会把你的代码写成:

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

      【讨论】:

      • 在那个具体的例子中,你甚至可以更进一步,使它成为const char* const StrArray[5] = { /* whatever */ }; :))
      【解决方案5】:

      只有指针数组在栈上,字符串常量不在。

      【讨论】:

        猜你喜欢
        • 2013-12-05
        • 1970-01-01
        • 2013-10-28
        • 2019-07-23
        • 1970-01-01
        • 2011-01-06
        • 2011-08-15
        • 1970-01-01
        • 2016-08-06
        相关资源
        最近更新 更多