自赋值在变量定义期间有什么作用吗?
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
被赋值)。
永远不要使用前一个代码,应该更正为后者。
我面前有一些这样的代码:
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
被赋值)。
永远不要使用前一个代码,应该更正为后者。