结构中的数组分配在哪里?
Where are arrays in structs Allocated?
假设我有以下结构。
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;
};
我可以 "memcpy" 将 Vector3 的内容转换为三元组吗?
最后但同样重要的是,这个结构呢?与 Vector3 相同的规则?
struct Matrix3{
double Values[3][3];
};
结构是作为一个整体分配的,包括数组。
struct Vector3 v1;
这里,如果这是一个局部声明(在函数内),则结构的全部内容(三个双精度数的数组)分配在堆栈中,在其他地方则分配在静态数据区域中。从不在堆上。
Could I "memcpy" the contents of a Vector3 to a Triplet?
这可能行得通,但这样做很危险,因为结构内部结构字段的布局取决于编译器,Triplet
可能在双打之间有填充。一般来说,你不应该 memcpy
不同的结构。
关于最后一个例子(struct中的二维数组),是的,它和前面一样,九个值是在struct中分配的。
Where are arrays in structs Allocated
结构本身被分配的相同位置,根据您如何实例化结构,是在堆栈上还是在堆上。
struct Vector3 v1;
在堆栈上分配 Vector3 所需的所有内存。
Could I "memcpy" the contents of a Vector3 to a Triplet?
这取决于结构在您的目标平台上的打包方式以及您的编译器设置和可能影响打包的#pragma。没有一般保证您可以 memcopy 数据。它可以在 某些 平台上运行,然后在其他平台上可能会失败。
1) The 'doubles' of .Values are allocated on the stack or the heap?
它们是您 struct
的 部分 ,这就是 "member" 的意思。所以他们被分配到你的 struct
所在的地方。
Could I "memcpy" the contents of a Vector3 to a Triplet?
总的来说:没有。例如,数组是连续的,结构可以在其成员之间包含未使用的填充。归结为您的 triplet 结构与您的 vector3 结构不兼容。
edit: anatolyg 对这个问题的评论让我知道有人是怎么想出来的,事实上,这可能是因为数组和指针经常 "look" 相似(一些非常糟糕的资源甚至声称它们是相同的)。
他们不是!
数组其实就是同一类型变量的序列,多维数组更是如此。 存储的对象无非是连续声明的元素总数(阅读:值)。
对于指针来说,存储的对象是一个地址
经常混淆的是两件事:
- 无法将数组传递给函数。当您这样做时,它会隐式转换为指针(该函数获得指向数组的指针)。
- 可能是为了便于使用,索引运算符(
[]
)也适用于指针。
索引 ([]
) 内部发生的事情是不同的。对于数组,它仅表示该数组的索引元素。(*) 对于指针,假定指针实际指向数组,因此指针在取消引用之前按给定索引递增(从而访问索引元素指向的数组)。
示例:
int a[5];
int *p;
现在 a[3]
只访问 a
的第 4 个元素。但是 p[3]
实际上等同于 *(p+3)
.
(*) 事实上,*(a+3)
也是一个有效的表达式,并且根据 C 标准,它 是 等价于a[3]
因为 []
是根据指针算法定义的。它之所以有效,是因为数组 总是 在用作一个数组时隐式转换为指针。不要让这让你迷惑,它仍然不是一个指针
假设我有以下结构。
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;
};
我可以 "memcpy" 将 Vector3 的内容转换为三元组吗?
最后但同样重要的是,这个结构呢?与 Vector3 相同的规则?
struct Matrix3{
double Values[3][3];
};
结构是作为一个整体分配的,包括数组。
struct Vector3 v1;
这里,如果这是一个局部声明(在函数内),则结构的全部内容(三个双精度数的数组)分配在堆栈中,在其他地方则分配在静态数据区域中。从不在堆上。
Could I "memcpy" the contents of a Vector3 to a Triplet?
这可能行得通,但这样做很危险,因为结构内部结构字段的布局取决于编译器,Triplet
可能在双打之间有填充。一般来说,你不应该 memcpy
不同的结构。
关于最后一个例子(struct中的二维数组),是的,它和前面一样,九个值是在struct中分配的。
Where are arrays in structs Allocated
结构本身被分配的相同位置,根据您如何实例化结构,是在堆栈上还是在堆上。
struct Vector3 v1;
在堆栈上分配 Vector3 所需的所有内存。
Could I "memcpy" the contents of a Vector3 to a Triplet?
这取决于结构在您的目标平台上的打包方式以及您的编译器设置和可能影响打包的#pragma。没有一般保证您可以 memcopy 数据。它可以在 某些 平台上运行,然后在其他平台上可能会失败。
1) The 'doubles' of .Values are allocated on the stack or the heap?
它们是您 struct
的 部分 ,这就是 "member" 的意思。所以他们被分配到你的 struct
所在的地方。
Could I "memcpy" the contents of a Vector3 to a Triplet?
总的来说:没有。例如,数组是连续的,结构可以在其成员之间包含未使用的填充。归结为您的 triplet 结构与您的 vector3 结构不兼容。
edit: anatolyg 对这个问题的评论让我知道有人是怎么想出来的,事实上,这可能是因为数组和指针经常 "look" 相似(一些非常糟糕的资源甚至声称它们是相同的)。
他们不是!
数组其实就是同一类型变量的序列,多维数组更是如此。 存储的对象无非是连续声明的元素总数(阅读:值)。
对于指针来说,存储的对象是一个地址
经常混淆的是两件事:
- 无法将数组传递给函数。当您这样做时,它会隐式转换为指针(该函数获得指向数组的指针)。
- 可能是为了便于使用,索引运算符(
[]
)也适用于指针。
索引 ([]
) 内部发生的事情是不同的。对于数组,它仅表示该数组的索引元素。(*) 对于指针,假定指针实际指向数组,因此指针在取消引用之前按给定索引递增(从而访问索引元素指向的数组)。
示例:
int a[5];
int *p;
现在 a[3]
只访问 a
的第 4 个元素。但是 p[3]
实际上等同于 *(p+3)
.
(*) 事实上,*(a+3)
也是一个有效的表达式,并且根据 C 标准,它 是 等价于a[3]
因为 []
是根据指针算法定义的。它之所以有效,是因为数组 总是 在用作一个数组时隐式转换为指针。不要让这让你迷惑,它仍然不是一个指针