【问题标题】:Where are arrays in structs Allocated?结构中的数组在哪里分配?
【发布时间】:2015-10-27 18:36:46
【问题描述】:

假设我有以下结构。

struct Vector3{
    double Values[3];
};

我知道我可以这样做:

struct Vector3 v1;
v1.Values[0] = -1;
printf("%f", vi.Values[0]);

它会工作得很好。我不必 malloc/calloc .Values。 使用 -c99 -Wall 编译不会给我任何警告。 但我对这种结构有疑问。

在这种情况下,v1 是一个局部变量:

  • .Values 的“双精度值”分配在堆栈还是堆上?
  • 如果它们是在堆上分配的,这段代码是否保证 总是工作?还是依赖于编译器?

如果有这个其他结构

struct Triplet{
    double First;
    double Second;
    double Third;
};

我可以将 Vector3 的内容“memcpy”到 Triplet 吗?

最后但同样重要的是,这个结构呢?和 Vector3 的规则一样吗?

struct Matrix3{
    double Values[3][3];
};

【问题讨论】:

  • 除非您执行“malloc”,否则在这种情况下,所有内容都分配在堆栈上。检查结构的大小。
  • 也许指针和数组的相似性让你感到困惑。数组不是指针 - 您的 Vector3 与您的 Triplet 非常相似,并且与指针完全不同 - 所以不需要 malloc 等。
  • @anatolyg:这基本上就是我要说的。建议阅读:comp.lang.c FAQ 的第 6 节。
  • @anatolyg 可以真正解释这个问题,所以我决定在我的回答中详细说明一下。

标签: c struct malloc


【解决方案1】:

结构中的数组在哪里分配

结构本身的分配位置相同,在堆栈或堆上,具体取决于您如何实例化结构。

结构向量3 v1;

在堆栈上分配 Vector3 所需的所有内存。

我可以将 Vector3 的内容“memcpy”到 Triplet 吗?

这取决于结构在目标平台上的打包方式以及编译器设置以及可能影响打包的#pragma。不能保证您可以只对数据进行 memcopy。它可以在一些平台上运行,然后在其他平台上可能会失败。

【讨论】:

  • 作者写了struct Vector3 v1;,意思是使用了栈,不是吗?)
  • 我明白了。所以如果我将它分配为局部变量,我不必“释放”数组?
  • @Trauer 请注意,即使您 malloc struct 您只需要 free 结构本身,而不是其中的数组。
  • 完美。感谢 Eric 和 Kninnug。很好的答案!
  • 所以如果我将它分配为局部变量,我不必“释放”数组? local 与作用域有关,或变量的生命周期,而不是它是在堆上还是在堆栈上。将它创建为 local 还是 global 都没有关系,如果你没有使用 [m][c][re]alloc,则不必释放某些东西创建它。
【解决方案2】:

1) .Values 的'doubles'是分配在堆栈还是堆上?

它们是您的struct一部分,这就是“成员”的意思。因此,它们被分配到您的struct 分配的任何位置。

我可以将 Vector3 的内容“memcpy”到 Triplet 吗?

一般来说:没有。例如,数组是连续的,结构可以在其成员之间包含未使用的填充。这归结为您的 triplet 结构与您的 vector3 结构不兼容。

edit:anatolyg 对这个问题的评论让我知道有人如何想出它,事实上,这可能是因为数组和指针通常“看起来”相似(甚至一些非常糟糕的资源声称它们是相同的)。

他们不是!

数组实际上只是相同类型的变量序列,对于多维数组也是如此。 存储的对象只不过是一行中声明的元素总数(阅读:)。

对于指针,存储的对象是一个地址。

经常令人困惑的是两件事:

  1. 无法将数组传递给函数。这样做时,它会隐式转换为指针(函数获取指向数组的指针)。
  2. 可能为了便于使用,索引运算符 ([]) 也适用于指针。

索引 ([]) 内部发生的情况有所不同。对于数组,它只表示该数组的索引元素。(*)对于指针,假设指针实际上指向一个数组,因此指针在取消引用之前按给定索引递增(因此访问的索引元素指向的数组)。

例子:

int a[5];
int *p;

现在a[3] 只访问a 的第四个元素。但p[3]实际上等价于*(p+3)

(*) 事实上,*(a+3) 也是一个有效的表达式,并且根据 C 标准,它 等价于 a[3],因为定义了 []在指针算术方面。它之所以有效,是因为数组在用作一个数组时总是隐式转换为指针。不要让这个混淆你,它仍然不是一个指针

【讨论】:

    【解决方案3】:

    结构是作为一个整体分配的,包括数组。

    struct Vector3 v1;
    

    如果这是本地声明(在函数内部),则结构的全部内容(三个双精度数组)在堆栈中分配,其他地方则在静态数据区域中。永远不会在堆上。

    我可以将 Vector3 的内容“memcpy”到 Triplet 吗?

    这可能可行,但这样做很危险,因为结构内的结构字段布局取决于编译器,Triplet 可能在双精度之间有填充。一般来说,你不应该 memcpy 不同的结构。

    关于最后一个例子(结构体内部的二维数组),是的,和上一个一样,九个值分配在结构体内部。

    【讨论】:

      猜你喜欢
      • 2012-10-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-24
      • 2016-02-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多