这可能是我做错的非常愚蠢的事情,但我无法弄清楚它是什么。
我有一个结构 PDRect
,它的成员是一个 PDPoint
和 PDSize
:
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.width
和 rect.origin.height
都存在并且等于 0,并且 rect.size.x
和 rect.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;
我仍然不确定我是否真的理解为什么这会产生影响,但它似乎已经解决了问题。
最佳答案
我认为问题的发生是因为您同时使用了匿名结构和类型定义。当 C 编译器看到
struct {...} name;
构造它实际上改变的是它
struct anonymous {...} name;
现在这是我认为正在发生的事情:...我说我认为是因为我无法重现您的示例。我只是将类型更改为 float 并在 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 h:0.500000 x:1.000000 y:1.000000
应该...
如果您可以尝试以下内容,那将会很有趣。更改其中一个结构以保持
整数并查看交换是否再次发生。还要尝试将 2 个字段初始化为非零值,以检查是您导致了它还是它的默认分配值。
我认为正在发生的事情是,对于您的代码,编译器会按以下顺序执行操作:
a) 它看到一个名为 anonymous 的结构接受 2 个 float ,将其存储在堆栈中并将其命名为 PDPoint
b)它看到一个名为 anonymous 的结构接受 2 个 float ,将其存储在堆栈中并将其命名为 PDSize
c) 在查找 PDPoint 以定义第三个结构时,它从堆栈中弹出()s 名为匿名的结构,该结构采用 2 个 float 。但此时它解析为 PDSize。
d) 对于 PDSize,只有 PDPoint 留在堆栈中,实际上它是一个名为 anonymous 的结构,需要 2 个 float 。 ;)
typedef 和声明结构的正确方法是
typedef struct name_t { ... } name;
虽然有些人会争辩说现在您可以放弃 _t 约定(它是为 POSIX 保留的)。 tl;dr:小心匿名结构。
关于c - 子结构最终包含错误的成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13443662/