【问题标题】:Cast a variable to union-type defined within a structure definition将变量强制转换为结构定义中定义的联合类型
【发布时间】:2019-03-19 13:15:50
【问题描述】:

实际上,我在 C 中将 unsigned int 变量转换为在结构类型声明中声明的联合类型有一些困难。

我需要像编写结构中定义的联合字段一样设置变量。

在包含的头文件中声明:

typedef struct {
    [...]

    union {
        unsigned long COMPLETE_VALUE;
        struct {
            unsigned long   UPPER:16;           /* [15:0] */
            unsigned long   LOWER:16;           /* [31:16] */
        } SUB_STRUCT;
    } UNION;

    [...]
} STRUCT_TYPE;

c 源文件中的变量:

STRUCT_TYPE *pStructure;                        /* the reference structure */
unsigned long dummyVar;                         /* dummy variable */

/* writing the upper field in the structure */
pStructure->UNION.SUB_STRUCT.UPPER = some_value;

问题: 是否可以使用结构类型 STRUCT_TYPE 的内部联合类型来修改“dummyVar”的值? 是否可以将变量强制转换为结构内定义的联合并访问子结构的字段?

如果可以如下所示或以类似方式修改变量,那将非常有用:

((<CAST>) dummyVar).UNION.SUB_STRUCT.UPPER = some_value;

注意事项: - STRUCT_TYPE 的声明不能更改。 - 结构 pStructure 不能被写入或编辑。 - pStructure 的访问行为需要复制到 dummyVar。

这在 C 中是否可能?

提前谢谢你!

马丁

【问题讨论】:

  • 你的代码确实犯了一个很大的错误:它假设sizeof(long) == 4。情况并非总是如此。除了char(其中sizeof(char) == 1 始终为真)之外,C 中没有任何内置类型具有固定大小。你只知道sizeof(char) &lt;= sizeof(short) &amp;&amp; sizeof(short) &lt;= sizeof(int) &amp;&amp; sizeof(int) &lt;= sizeof(long) &amp;&amp; sizeof(long) &lt;= sizeof(long long)sizeof(long) == 8 在 64 位系统上并不少见。
  • 至于你的问题,你的问题是什么?我的意思是,您试图解决的原始问题是什么? 为什么您想使用dummyVar 作为联合体?为什么不能只使用简单的按位运算(如uint32_t dummyVar = 0; dummyVar |= (some_value &lt;&lt; 16);)?
  • 或者更重要的是,在 64 位系统上sizeof(long) == 4不常见的(仅在 Windows 上!)
  • 虽然char的大小定义了测量其他大小的单位,即使它没有固定的位数。
  • UPPER:16; /* [15:0] */ 无论字节顺序如何都是完全错误的。你怎么知道位域中的哪些 16 位是哪些位?它不是由 C 语言指定的。

标签: c struct casting union typedef


【解决方案1】:

是否可以使用结构类型 STRUCT_TYPE 的内部联合类型来修改“dummyVar”的值?

可能不会,因为你有这个:

typedef struct {
    [...]

    union {

我假设[...] 表示那里放置了结构成员。

是否可以将变量强制转换为结构中定义的联合并访问子结构的字段?

除非它是结构的初始部分,否则它是有问题的。将联合拆分为不与结构紧密耦合的单独 typedef 可能会更聪明。

此外,联合使用的位域不是标准化的,您无法知道它们是如何以可移植的方式在内存中结束的。

这里的聪明做法可能是忘记所有关于结构的事情并简单地做

uint32_t u32 = ...
uint16_t ms = u32 >> 16;
uint16_t ls = u32 & 0xFFFFu;

无论位域实现和字节序如何,此代码都是可移植的。

【讨论】:

    【解决方案2】:

    可以使用内部修改“dummyVar”的值 结构类型 STRUCT_TYPE 的联合类型?

    尽管考虑了大小和表示,不,在您的示例中不能将 anything 转换为内部联合类型,因为类型转换仅适用于标量类型。有些游戏你可以用指针和脆弱的代码重复来玩,但我强烈建议不要使用这种恶作剧,我拒绝举例说明。

    但是,如果您想将 dummyVar 的值设置为与 STRUCT_TYPE.UNION.COMPLETE_VALUE 对应的值,以获取 UPPERLOWER 的某些特定值,那么在 C99 及更高版本中,您可以通过复合文字来执行此操作:

    dummyVar = ((STRUCT_TYPE) { .UNION = { .SUB_STRUCT = { some_upper, some_lower } } }).UNION.COMPLETE_VALUE;
    

    请注意,尽管(STRUCT_TYPE) 片段类似于强制转换,但它只是复合文字语法的一部分。不能转换为结构类型,也不能转换为联合类型。

    或者,在未定义 STRUCT_TYPE 的翻译单元中,您可以为内部联合类型编写复合文字,但它会很多更糟。由于该类型没有标签或别名,因此该类型的复合文字需要重现其完整定义。这种复合文字的类型在技术上与定义两者的任何翻译单元中的结构成员的类型不兼容,但实际上,我认为没有任何理由怀疑您会为 @ 获得相同的值987654328@无论哪种方式。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-27
      • 1970-01-01
      • 1970-01-01
      • 2020-05-30
      相关资源
      最近更新 更多