struct {...}和struct {union {struct {...}}}之间有什么区别?

时间:2011-09-11 05:48:53

标签: c winapi struct unions

是否有DISK_DETECTION_INFO is defined as

的原因
typedef struct _DISK_DETECTION_INFO {
  DWORD          SizeOfDetectInfo;
  DETECTION_TYPE DetectionType;
  union {
    struct {
      DISK_INT13_INFO    Int13;
      DISK_EX_INT13_INFO ExInt13;
    };
  };
} DISK_DETECTION_INFO, *PDISK_DETECTION_INFO;

而不是

typedef struct _DISK_DETECTION_INFO {
  DWORD          SizeOfDetectInfo;
  DETECTION_TYPE DetectionType;
  DISK_INT13_INFO    Int13;
  DISK_EX_INT13_INFO ExInt13;
} DISK_DETECTION_INFO, *PDISK_DETECTION_INFO;

或者我只是过度分析这段代码?

4 个答案:

答案 0 :(得分:6)

可以说,这是一个错误。但是,可能我们只给出了结构的公共定义。在内部(当由Windows内核使用时),它可以定义为:

typedef struct _DISK_DETECTION_INFO {
  DWORD          SizeOfDetectInfo;
  DETECTION_TYPE DetectionType;
  union {
    struct {
      DISK_INT13_INFO    Int13;
      DISK_EX_INT13_INFO ExInt13;
    };
    DISK_INTERNAL_INFO   Private; // Used internally, when DetectionType = -1
  };
} DISK_DETECTION_INFO, *PDISK_DETECTION_INFO;

我不会将其视为可维护,安全或便携,但它可能

DISK_INTERNAL_INFO甚至可能超过匿名struct的大小 - 只要用户从不实例化对象本身,该技术甚至可能被认为对于将额外数据隐藏在远离用户但保留它的情况下有用结构。他们永远不会“看到”过去的匿名struct

答案 1 :(得分:0)

行为之间存在非常明显的差异:在第一种情况下,初始化Int13时,ExtInt13DISK_DETECTION_INFO均未初始化。在后一种情况下,所有四个字段都被初始化。

MSVC有一系列古怪的扩展,包括结构末尾的可变大小的数组,其自动初始化行为可能是不合需要的。

编辑:关于“初始化”:

我们说结构是

typedef struct _foo {
  int bar;
  union {
    struct {
      int baz;
      int wee;
    };
  };
} foo;

然后,写foo x = { 1; }不会给baz或wee赋值(它们在技术上是不确定的)。如果结构是

typedef struct _foo {
  int bar;
  int baz;
  int wee;
} foo;

然后,写foo x = { 1; }确实分配了baz = 0和wee = 0

答案 2 :(得分:0)

我认为有合理的证据表明有人在编写原始DISK_DETECTION_INFO结构定义时犯了一个简单的错误。这个错误逃到了野外,所以修复它已经太晚了。

头文件中的定义是:

typedef struct _DISK_DETECTION_INFO {
        DWORD SizeOfDetectInfo;
        DETECTION_TYPE DetectionType;
        union {
                struct {

                        //
                        // If DetectionType == DETECTION_INT13 then we have just the Int13
                        // information.
                        //

                        DISK_INT13_INFO Int13;

                        //
                        // If DetectionType == DETECTION_EX_INT13, then we have the
                        // extended int 13 information.
                        //

                        DISK_EX_INT13_INFO ExInt13;     // If DetectionType == DetectExInt13
                } DUMMYSTRUCTNAME;
        } DUMMYUNIONNAME;
} DISK_DETECTION_INFO, *PDISK_DETECTION_INFO;

文档内容如下:

  

如果DetectionType为DetectInt13,则union为DISK_INT13_ INFO结构。

     

如果DetectionType为DetectExInt13,则union为DISK_EX_ INT13_INFO结构。

因此,DISK_INT13_INFODISK_EX_INT13_INFO最初的意图似乎很可能被置于一个联盟中,因为它们是相互排斥的。

答案 3 :(得分:-4)

当一组字段具有互斥访问权限时,通常使用Union来节省空间。也就是说,当一个活跃时,另一个活动不能。与为所有字段分配空间相反,空间仅分配给最大的空间。该空间可与其他领域互换使用。如链接中所述,取决于DetectionType字段,它是Int13或ExInt13是活动的。两者都使用相同的分配空间。