内存分配相同的结构

时间:2010-07-14 23:26:06

标签: c++ pointers struct

所以我在教我的朋友指点。在这样做时,我注意到两个相同结构的地址完全背靠背。

struct Foo
{
    int a;
};

struct Bar
{
    int b;
};

允许我这样做:

Foo foo; foo.a = 100;
Bar bar; bar.b = 100;

Foo *pFoo = &foo;
Bar *pBar = &bar;

(pFoo+1)->a = 200;

这会覆盖bar.b中的值并将其设置为200.

现在,我并没有质疑做这样事情的优点 - 它可能永远不会在真正的节目中看到光明。我只是想知道,操作系统是否总是背靠背地分配相同的结构?如果在给定区域内有足够的可用内存空间。

6 个答案:

答案 0 :(得分:8)

不,不一定。某些体系结构/编译器可能会在边界上对齐结构,使得数组中的结构与调用堆栈上的结构之间存在不同的间距。你在调用堆栈上分配并将它们视为一个连续的数组,这是一个不可靠的假设。

答案 1 :(得分:6)

操作系统不为本地变量分配堆栈空间,编译器会这样做。 C ++编译器不保证分配顺序。

答案 2 :(得分:4)

否 - 编译器/链接器通常会将变量放在与源文件中位置无关的完全不同的位置。

我非常高兴能够使用从汇编转换的C代码,这些代码在整个地方做出了这个假设(在汇编中,当你在同一段/段中有2个变量彼此相邻时,这就是你在图片中得到的结果。)

那不好玩......

请注意,您可以使用工具(例如,链接器配置文件或编译器编译指示),这些工具可以控制内存中变量的位置。但在那时,你肯定处于“特定于实现”的领域,你仍然可能不得不处理对齐问题和诸如此类的问题(尽管结构大小相同,这可能不会成为一个问题)。

将2个结构彼此相邻的可移植方法是将它们包装在另一个结构中(同样,可能仍然存在指针算术和别名问题)。

答案 3 :(得分:4)

不,这不能保证有效。

首先,无法保证在内存中放置不相关的对象。保证对象在内存中连续放置的唯一时间是

  • 如果您自己将它们放在一起(例如,您手动分配一些字节并将它们一个接一个地放置)或
  • 如果它们在一个数组中(数组元素总是连续的)

因此,以下内容有效:

int ints[2];
*(&ints[0] + 1) = 42;

问题中的代码无效,因为foobar对象完全不相关,可以放在内存中的任何位置。

有一个相关的问题,在结构中可能有未命名的填充字节

    结构成员之间的
  • (以便成员正确对齐)和
  • 在结构的末尾
  • (以便该结构类型的对象可以连续放置在数组中)

这意味着以下内容无效,因为Foo末尾可能有未命名的填充:

Foo foos[2];
*(&foos[0].a + 1) = 42;

通常,除非它们在数组中,否则不应该依赖于两个对象相对于彼此的放置。在源代码中对象是否彼此相邻声明,它们具有相同的类型,或者它们具有相同的大小并不重要:根本无法保证。

答案 4 :(得分:1)

我记得在gcc上遇到使用整个程序优化的情况,它在整个优化过程中完全重新排序了所有全局变量。也就是说,对于C ++中的单独变量,这种布局没有这样的保证。

答案 5 :(得分:1)

这不仅仅发生在结构上。个别变量通常是连续的,但正如大家所说的那样,这是不可保证的(实际上,在我的方框中,以下示例的顺序是反转的)

int a,b;
int *pa=&a;
int *pb=&b;
a=1;
b=2;
*(pa)=3;
*(pb+1)=4;
printf("a value: %i \tb value: %i\n", *pa, *pb);

结果是


a value: 4  b value: 2