我想用单个指针访问连续声明的相同类型的成员数组。
所以example说我有:
struct S
{
double m1[2];
double m2[2];
}
int main()
{
S obj;
double *sp = obj.m1;
// Code that maybe unsafe !!
for (int i(0); i < 4; ++i)
*(sp++) = i; // *
return 0;
}
在什么情况下,行(*)有问题?
我知道当虚拟函数存在时肯定存在问题,但我需要比我的假设更有条理的答案
答案 0 :(得分:3)
您可以确定结构的成员按照它们出现的顺序存储在contiguos字节块中。此外,阵列的元素是连续的。所以,似乎一切都很好 这里的问题是没有标准的方法来知道结构中连续成员之间是否存在填充字节 因此,假设根本没有填充字节是不安全的。
如果您可以充分肯定,由于某些特定原因,没有填充字节,那么4个double
元素将是连续的,如您所愿。
答案 1 :(得分:2)
C ++标准对&#34;普通旧数据&#34;的布局做出了一定的保证。 (或在C ++ 11中,标准布局)类型。在大多数情况下,这些都继承了C处理此类数据的方式。
以下内容仅适用于&#34;普通旧数据&#34; /&#34;标准布局&#34;结构和数据。
如果你有两个具有相同初始顺序和参数类型的结构,则将一个指针指向一个指向另一个的指针并访问它们的公共初始前缀是有效的,并将访问相应的字段。这被称为&#34;布局兼容&#34;。如果你有一个结构X和一个结构Y,这也适用,并且X是结构Y的第一个元素 - 指向Y的指针可以转换为指向X的指针,它将访问X子结构的字段。收率
现在,虽然这是一个常见的假设,但我不知道C或C ++的要求是数组和以相同类型和数字的字段开头的结构与数组布局兼容。
你的情况有点类似,因为我们在一个结构中有两个彼此相邻的数组,你将它视为一个大小等于这两个数组大小之和的大数组。这是一个相对普遍和安全的假设,它可以工作,但我不知道它实际上有效的标准保证。
在这种未定义的行为中,您必须检查您的特定编译器保证(事实上或显式)关于普通旧数据/标准布局数据的布局,因为C ++标准不保证您的代码按照您的要求执行做。