C语言 编译时的强制转换

gcmastyq  于 2023-04-11  发布在  其他
关注(0)|答案(1)|浏览(147)

考虑以下联合:

/**
 * @brief   Holding parameter 16-bit value variant representation
 */
typedef union
{
    uint16_t    u;  /*!< unsigned integer 16-bit */

    int16_t     i;  /*!< signed integer 16-bit */

} hparamValue_t;

这个函数将这样一个union作为输入参数:

void hparam_set(const hparamValue_t value);

当调用这个函数时,我手头只有一个uint16_tint16_t。所以为了以一种“干净”的方式使用它,我这样做了:

uint16_t myVar; // somewhere

// when calling the function
hparamValue_t hpv;
hpv.u = myVar;
hparam_set(hpv);

但我更倾向于这个结构:

hparam_set(*((hparamValue_t*)&myVar));

虽然它看起来不是很明显,但它并没有强迫我创建一个额外的人工变量。问题是,强制转换为指针,然后是值,在编译时仍然会展开吗?这看起来很安全,我还缺少什么吗?

afdcj2ne

afdcj2ne1#

当使用不同于定义的类型访问对象时,我们必须考虑C 2018 6.5 7中的别名规则:
对象的存储值只能由具有以下类型之一的左值表达式访问:

  • 与对象的有效类型兼容的类型,
  • 与对象的有效类型兼容的类型的限定版本,
  • 是与对象的有效类型相对应的有符号或无符号类型的类型,
  • 作为与对象的有效类型的限定版本相对应的有符号或无符号类型的类型,
  • 在其成员中包括上述类型之一的聚合或联合类型(递归地包括子聚合或包含联合的成员),或者
  • 字符类型。

hparam_set(*((hparamValue_t*)&myVar));符合此规则,因为hparamValue_t是一个联合类型,它包含一个与myVar类型相同的成员。要考虑的第二个规则是,当指向一个对象类型的指针转换为指向另一个对象类型的指针时,如果被转换的指针不具有新类型所需的对齐,则C标准不定义行为。在指向uint16_t的指针被转换为仅包含16位成员的指针的情况下,联合的对齐要求与普通C实现中uint16_t的对齐要求相同,但C标准不要求这样。
另一种将hparamValue_t传递给hparam_set的方法是使用复合文字:

hparam_set((hparamValue_t) { .u = myVar });

复合文字的形式为(type) {initializers}initializers的形式与定义中的初始化器相同。复合文字是指定类型的未命名对象。在函数外部,它具有静态存储期限。在函数内部,它具有与在相同位置定义的普通对象相同的自动存储期限。

相关问题