【发布时间】:2021-06-06 10:23:01
【问题描述】:
我在我正在处理的项目中偶然发现了一些代码,我想确保正确理解它。 所以这里是:
uint16_t* tmp;
tmp = (uint16_t*) ((uint8_t*)getVariableAddress(variable) + offset);
tmp = (uint16_t*)((uint8_t*)tmp + otherOffset);
Set_Register((unsigned long) tmp[0]);
Set_OtherRegister((unsigned long) tmp[2]);
起初我在所有转换之间有点迷失,但我看到它的方式是 uint8_t* 被用于逐字节移动并将偏移值添加到我们放置在 tmp 中的基地址,这是第一部分这让我很困扰。 第二部分是在 uint16_t* 上使用 [] ,对此我完全不确定结果,有人愿意详细解释吗?
谢谢
【问题讨论】:
-
如果偏移量以字节为单位但类型为 16 位,则强制转换可确保指针算术正确。如果类型是 16 位,则
pointer + 1将2添加到指针值。至于tmp[2],这与*(tmp + 2)相同,并且转换应用于数据值,而不是指针类型。 -
值得注意的是,除非实际存储在该地址的内容确实是
uint16_t,否则此代码会调用未定义的行为错误。getVariableAddress做了什么,从它返回的指针指向哪里?这段代码很可能写错了。 -
项目中该代码的编写者可能希望了解将
uint8_t指针转换为uint16_t指针违反严格的别名规则。 -
代码可能从根本上被破坏了。正如@Pedro 所指出的,这违反了strict aliasing,因此是未定义的行为。由于alignment restrictions,它也可能是未定义的行为。不,it doesn't "work"。它只是没有失败还。
-
@AndrewHenle:作为“符合语言扩展”的一种形式,实现可以定义比标准规定的更多动作的行为。何时以这种方式扩展语言的问题是标准管辖范围之外的实施质量问题。依赖于此类扩展的代码不会严格符合,也不会 100% 可移植,但这并不意味着它不符合或损坏。在以所需方式扩展语言的实现上,它将 100% 可靠地工作。