考虑以下联合:
/**
* @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_t
或int16_t
。所以为了以一种“干净”的方式使用它,我这样做了:
uint16_t myVar; // somewhere
// when calling the function
hparamValue_t hpv;
hpv.u = myVar;
hparam_set(hpv);
但我更倾向于这个结构:
hparam_set(*((hparamValue_t*)&myVar));
虽然它看起来不是很明显,但它并没有强迫我创建一个额外的人工变量。问题是,强制转换为指针,然后是值,在编译时仍然会展开吗?这看起来很安全,我还缺少什么吗?
1条答案
按热度按时间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
的方法是使用复合文字:复合文字的形式为
(
type) {
initializers}
。initializers
的形式与定义中的初始化器相同。复合文字是指定类型的未命名对象。在函数外部,它具有静态存储期限。在函数内部,它具有与在相同位置定义的普通对象相同的自动存储期限。