结构中的数组在哪里分配?

时间:2015-10-27 18:36:47

标签: c struct malloc

假设我有以下结构。

struct Vector3{
    double Values[3];
};

我知道我可以这样做:

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

它会正常工作。我没有malloc / calloc的.Values。 用-c99 -Wall编译没有给我任何警告。 但我对这种结构有疑问。

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

  • .Values的'doubles'是在堆栈还是堆上分配的?
  • 如果在堆上分配它们,则保证此代码 总能工作?或者它是编译器依赖的吗?

如果有其他结构

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

我可以将一个Vector3的内容“memcpy”为Triplet吗?

最后但并非最不重要的是,这个结构怎么样?与Vector3相同的规则?

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

3 个答案:

答案 0 :(得分:4)

  

结构中的数组分配在哪里

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

  

struct Vector3 v1;

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

  

我可以将一个Vector3的内容“memcpy”为Triplet吗?

这取决于结构在目标平台上的打包方式以及您的编译器设置以及可能影响打包的#pragma。没有一般保证您可以只记忆数据。它可以在某些平台上运行,然后可以在其他平台上运行。

答案 1 :(得分:4)

  

1).Values的“双精度”是在堆栈还是堆上分配的?

他们是struct部分,这就是“成员”的含义。因此,只要分配struct,就会分配它们。

  

我可以将一个Vector3的内容“memcpy”为Triplet吗?

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

编辑:anatolyg对这个问题的评论给了我一个关于某人怎么想出来的想法,实际上,这可能是因为数组和指针经常“看起来”相似(甚至一些非常糟糕的资源甚至声称他们是一样的。)

他们不是!

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

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

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

  1. 数组无法传递给函数。执行此操作时,它会隐式转换为指针(函数获取指向数组的指针)。
  2. 可能为了易于使用,索引操作符[])也适用于指针。
  3. 索引([])内部发生的情况有所不同。对于数组,它只表示该数组的索引元素。(*)对于指针,假设指针实际指向数组,因此指针在解除引用之前递增给定的索引(从而访问索引的元素)数组指向)。

    示例:

    int a[5];
    int *p;
    

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

    (*)实际上,*(a+3)也是一个有效的表达式,根据C标准, 等同于a[3]因为{ {1}}是根据指针算术来定义的。它的工作原理是因为当用作一个数组时,数组总是隐式转换为指针。不要让这让你感到困惑,它仍然不是一个指针

答案 2 :(得分:2)

结构被分配为一个整体,包括数组。

struct Vector3 v1;

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

  

我可以将一个Vector3的内容“memcpy”为Triplet吗?

这可能会起作用,但这样做会很危险,因为struct中的struct字段的布局依赖于编译器,Triplet可以在double之间填充。一般来说,你不应该memcpy不同的结构。

关于最后一个例子(结构中的二维数组),是的,它与前一个相同,九个值在结构内部分配。