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

标签 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;

我仍然不确定我是否真的理解为什么这会产生影响,但它似乎已经解决了问题。

最佳答案

我认为问题的发生是因为您同时使用了匿名结构和类型定义。当 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/

相关文章:

c - Scanf 不接受输入字符

c - 是否可以仅使用 printf 语句来舍入 double?

c++ - c++ 是否提供了一种使整个结构常量(不可修改)的方法?

c - 结构体中的结构体数组中的 int 数组

c - 为什么 printf() 不给出任何错误和 scanf() 问题

c - 程序复制文件不正确

c - 带位字段的 QR 编码

c - c中的bsearch函数和结构

c - C中同一结构内的结构数组

将结构体成员复制到新结构体中