11

考虑以下结构:

struct Vector4D
{
   union
   {
      double components[4];
      struct { double x, y, z, t; } Endpoint;
   };
};

在我看来,我在 WinApi 的 IPAddress 结构中看到了类似的东西。这个想法是让我可以按索引和名称使用数组组件,例如:

Vector4D v;
v.components[2] = 3.0;
ASSERT(v.Endpoint.z == 3.0) //let's ignore precision issues for now

在 C++ 标准中,保证在 POD 结构的开头不会有“空”空间,也就是说,元素 x 将位于 Endpoint 结构的开头。目前很好。但是我似乎没有找到任何保证不会有空白或填充,如果你愿意的话,在xand y, or yandz等之间。虽然我还没有检查过 C99 标准。

问题是,如果 Endpoint 结构元素之间有一个空白空间,那么这个想法就行不通了。

问题:

  1. 我是对的,确实不能保证这将在 C 或 C++ 中工作。

  2. 这实际上适用于任何已知的实现吗?换句话说,您是否知道这不起作用的任何实现?

  3. 是否有任何标准(我的意思不是特定于编译器)的方式来表达相同的想法?也许 C++0x 对齐功能可能会有所帮助?

顺便说一句,这不是我在生产代码中做的事情,别担心,只是好奇。提前致谢。

4

4 回答 4

5
  1. 是的
  2. 取决于架构的对齐需求和编译器策略
  3. 不,但你可以制作一个对象包装器(但你最终会得到.z()而不是 just .z

大多数编译器应该支持使用编译指示或属性压缩结构。#pragma pack例如。

于 2011-06-23T10:20:50.253 回答
4

您可以通过引用数组的每个元素来规避任何内存对齐问题,只要您在类中的引用之前声明数组以确保它们指向有效数据。话虽如此,我怀疑对齐是否会成为双打的问题,但可能适用于其他类型(也许在 64 位拱上浮动?)

#include <iostream>
using namespace std;

struct Vector4D
{
    Vector4D() : components(), x(components[0]), y(components[1]), z(components[2]), t(components[3]) { }

    double components[4];

    double& x;
    double& y;
    double& z;
    double& t;
};

int main()
{
    Vector4D v;

    v.components[0] = 3.0;
    v.components[1] = 1.0;
    v.components[2] = 4.0;
    v.components[3] = 15.0;

    cout << v.x << endl;
    cout << v.y << endl;
    cout << v.z << endl;
    cout << v.t << endl;
}

希望这可以帮助。

于 2011-06-23T10:58:34.863 回答
2

谈到标准,它有两个问题:

  • 未指定写入联合中的元素并从另一个元素读取时会发生什么,请参阅 C 标准 6.2.6.1 和 K.1
  • 该标准不保证结构的布局与数组的布局相匹配,详见 C 标准 6.7.2.1.10。

话虽如此,实际上这将适用于普通编译器。事实上,这种代码被广泛传播,并且经常用于将一种类型的值重新解释为另一种类型的值。

于 2011-06-23T11:50:32.173 回答
0

填充字节不会导致问题,因为所有变量都是 type double。编译器会将Vector4D其视为double数组。这意味着,v.Endpoint.z本质上与v[2].

于 2011-06-23T10:33:28.060 回答