子结构最终包含错误的成员

时间:2012-11-18 19:21:12

标签: c struct

这可能是一件非常愚蠢的事情,我做错了,但我无法弄清楚它是什么。

我有一个结构PDRect,其成员是PDPointPDSize

typedef struct {
    GLfloat x, y;
} PDPoint;

typedef struct {
    GLfloat width, height;
} PDSize;

typedef struct {
    PDPoint origin;
    PDSize size;
} PDRect;

当我实例化一个时,就像这样:

PDRect rect = {
    .origin = {
        .x = 0,
        .y = 0
    },
    .size = {
        .height = .5,
        .width = .5
    }
};

调试器表示rect.origin.widthrect.origin.height都存在且等于0,rect.size.xrect.size.y都存在并且相等.5。我不知道为什么会这样。

编辑清晰度:我的困惑是为什么rect.origin(它是一个PDPoint)具有与之关联的高度和宽度值,而rect.size(它是一个PDSize)具有与之关联的x和y值。原点不应该只有x和y,并且尺寸只有高度和宽度吗?

编辑:它实际上修复它以使它们非匿名声明,即:

typedef struct _PDPoint {
    GLfloat x, y;
} PDPoint;

typedef struct _PDSize {
    GLfloat width, height;
} PDSize;

typedef struct _PDRect {
    PDPoint origin;
    PDSize size;
} PDRect;

我仍然不确定我是否真的理解为什么会有所作为,但似乎已经解决了这个问题。

1 个答案:

答案 0 :(得分:1)

我认为问题发生的原因是你在同一时间使用匿名结构和typedefing。当C编译器看到

struct {...} name;

构建它实际上是将其改为

struct anonymous {...} name;

现在这就是我认为正在发生的事情:......我说我认为因为我无法重现你的榜样。我刚刚将类型更改为浮点数并在FreeBSD amd64 / gcc版本4.2.1 20070831上运行。代码如下。

#include <stdio.h>

typedef struct {
  float x, y;
} PDPoint;

typedef struct {
  float width, height;
} PDSize;

typedef struct {
  PDPoint origin;
  PDSize size;
} PDRect;

int main(int argc, char *argv[]) {
  PDRect rect = {
    .origin = {
      .x = 1,
      .y = 1
    },
    .size = {
      .height = .5,
      .width = .5
    }
  };
  printf("w:%f h:%f x:%f y:%f\n",rect.size.width,rect.size.height,
      rect.origin.x,rect.origin.y);
  return 0;
}

输出

  

w:0.500000小时:0.500000 x:1.000000 y:1.000000

应该...... 如果你可以尝试以下它会很有趣。改变其中一个结构 整数,看看交换是否再次发生。同时尝试将2个字段初始化为非零值,以检查是否导致它或其默认指定值  我认为正在进行的是,使用您的代码,编译器按顺序执行操作:

a)它看到一个名为anonymous的结构,它占用2个浮点数,将其存储在一个堆栈中,并将其命名为PDPoint

b)它看到一个名为anonymous的结构,它占用2个浮点数,将其存储在堆栈中并将其命名为PDSize

c)在查找PDPoint以定义第三个结构时,它从堆栈中弹出()s,结构称为匿名,需要2个浮点数。但在这一点上,这解决了PDSize。

d)对于PDSize ony PDPoint留在堆栈上,实际上它是一个名为匿名的结构,需要2个浮点数。 ;)

typedef和声明结构的正确方法是

typedef struct name_t { ... } name;

虽然有些人会争辩说,现在你可以放弃_t约定(它保留给POSIX)。 tl; dr:小心匿名结构。