自赋值在变量定义期间有什么作用吗?

Does self-assignment do anything during variable definition?

我面前有一些这样的代码:

uint16_t a = a = (uint16_t) (bPtr);

这有什么我不知道的特别之处吗?还是等同于:

uint16_t a = (uint16_t) (bPtr);

我猜这只是组合的错字

uint16_t a;
a = (uint16_t) (bPtr);

在这种情况下,它也是一样的。没有区别。

但是如果变量被声明为volatile它会写两次。我在硬件上使用(由于硅错误)其中一个硬件寄存器必须写入两次

void writeREG(unsigned addr, uint32_t val)
{
    *(volatile uint32_t *)addr = *(volatile uint32_t *)addr = val;
}

和代码:

writeREG:
        str     r1, [r0]
        str     r1, [r0]
        bx      lr

C 标准没有很好地定义初始化器中初始化和表达式求值的混合,特别是在这些初始化器中的副作用方面。然而,uint16_t a = a = (uint16_t) (bPtr); 最好被视为未定义行为,因为它违反了 C 2018 6.5 2:

If a side effect on a scalar object is unsequenced relative to either a different side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined…

uint16_t a = a = (uint16_t) (bPtr);中,赋值具有更新标量对象a的副作用。关于初始化是否像创建对象时发生的赋值一样,初始化没有很好地定义。在C标准没有这样的规范的情况下,相对于赋值的副作用,我们应该认为它是无序的,因此6.5 2呈现了C标准未定义的程序行为。

相比之下,uint16_t a = (uint16_t) (bPtr);是完全定义的(只要bPtr被赋值)。

永远不要使用前一个代码,应该更正为后者。