【问题标题】:How is memory allocated for an implicitly defined multidimensional array in C99?如何为 C99 中隐式定义的多维数组分配内存?
【发布时间】:2012-11-30 19:06:42
【问题描述】:

我正在尝试编写一个 C99 程序,并且我有一个隐式定义的字符串数组:

char *stuff[] = {"hello","pie","deadbeef"};

由于没有定义数组维度,那么为每个字符串分配多少内存?是否所有字符串都分配了与定义中最大字符串相同数量的元素?例如,下面的代码是否等同于上面的隐式定义:

char stuff[3][9];
strcpy(stuff[0], "hello");
strcpy(stuff[1], "pie");
strcpy(stuff[2], "deadbeef");

或者是每个字符串只分配了它在定义时所需的内存量(即stuff[0]拥有一个6元素的数组,stuff[1]拥有一个4的数组 个元素,stuff[2] 包含 9 个元素的数组)?

【问题讨论】:

  • 数组衰减为指针——但它们不是一回事!

标签: c arrays memory-management multidimensional-array c99


【解决方案1】:

在第一个例子中,我想它是一个锯齿状数组

它声明了一个指向 char 的 const 指针数组。所以字符串文字可以是任意长的。字符串的长度与数组列独立

在第二个中.. 每行的字符数 (string) 长度必须为 9(由您的列大小指定)或更少。

【讨论】:

    【解决方案2】:

    是否所有字符串都分配了与最大的相同数量的元素 定义中的字符串?

    不,只分配了 3 个指针,它们指向 3 个字符串字面量。

    char *stuff[] = {"hello","pie","deadbeef"};
    

    char stuff[3][9];
    

    完全不等价。第一个是一个由 3 个指针组成的数组,而第二个是一个二维数组。

    对于第一个唯一的指针被分配并且它们指向的字符串字面量可以存储在只读部分中。第二个分配在自动存储(通常是堆栈)上。

    【讨论】:

      【解决方案3】:
      char *stuff[] = {"hello","pie","deadbeef"};
      

      不是多维数组!它只是一个指针数组。

      为每个字符串分配多少内存?

      字符数加上空终止符。与任何字符串文字相同。

      我想你想要这个:

      char foo[][10] = {"hello","pie","deadbeef"};
      

      这里,10 是每个字符串的空间量,所有字符串都在连续的内存中。因此,小于 10 的字符串会有填充。

      【讨论】:

        【解决方案4】:

        图片可以提供帮助 — ASCII 艺术很有趣(但很费力)。

        char *stuff[] = {"hello","pie","deadbeef"};
        
        +----------+          +---------+
        | stuff[0] |--------->| hello\0 |
        +----------+          +---------+      +-------+
        | stuff[1] |-------------------------->| pie\0 |
        +----------+          +------------+   +-------+
        | stuff[2] |--------->| deadbeef\0 |
        +----------+          +------------+
        

        为一维指针数组分配的内存是连续的,但不能保证数组中保存的指针指向连续的内存部分(这就是指针行长度不同的原因)。

        char stuff[3][9];
        strcpy(stuff[0], "hello");
        strcpy(stuff[1], "pie");
        strcpy(stuff[2], "deadbeef");
        
        +---+---+---+---+---+---+---+---+---+
        | h | e | l | l | o | \0| x | x | x |
        +---+---+---+---+---+---+---+---+---+
        | p | i | e | \0| x | x | x | x | x |
        +---+---+---+---+---+---+---+---+---+
        | d | e | a | d | b | e | e | f | \0|
        +---+---+---+---+---+---+---+---+---+
        

        为二维数组分配的内存是连续的。 x 表示未初始化的字节。注意stuff[0]是指向'hello'的'h'的指针,stuff[1]是指向'pie'的'p'的指针,stuff[2]是指向'deadbeef'的第一个'd'的指针' (并且stuff[3] 是一个不可取消引用的指针,指向 'deadbeef' 之后的空字节之外的字节)。

        图片很不一样。

        请注意,您可以编写以下任何一种:

        char stuff[3][9] = { "hello", "pie", "deadbeef" };
        char stuff[][9]  = { "hello", "pie", "deadbeef" };
        

        您将拥有与二维数组图中所示相同的内存布局(除了 x 将被归零)。

        【讨论】:

        • 这很好地解释了内存中发生的事情!有没有人参考 C99 标准中描述此行为的位置?
        • 6.2.6 类型的表示。
        猜你喜欢
        • 2021-11-15
        • 2021-07-21
        • 2021-03-02
        • 2015-02-01
        • 1970-01-01
        • 2019-06-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多