我对这是否是严格的别名违规或调用未定义的行为感到困惑。多人告诉我这不是违规,并且没有UB,但是从阅读C ++规范听起来像是在做任何取消引用类型转换指针(除非它只是cv-casted或转换为兼容类型或char)是UB。
SWAP
(这是一个有点人为的例子;实际上uint16_t
可能是需要char
的第三方函数。)
故事是否因为我们检查了对齐而变化,对类型的大小有信心并且不关心字节序?我想,剩下的问题将是优化器消除死代码。
如果这是非法的,您如何有效地将int16
缓冲区(例如来自文件)解释为其预期类型(例如=INDEX(A1:A100,SUMPRODUCT(--(C1:C100=MAX(IF(B1:B100="fruit",C1:C100,"")))*(B1:B100="fruit")*ROW(1:100)))
s)?我很熟悉通过联合进行转换,但我并没有真正看到它有何不同(参见casting through a union(1),除了告诉编译器它不能消除死代码。
答案 0 :(得分:4)
多人告诉我,这不是违规,而且没有UB
那些人错了。这段代码:
uint16_t* data16 = reinterpret_cast<uint16_t*>(data);
是已定义的行为,如果,且仅当时,uint16_t
处有data
类型的对象。也就是说,如果我把你的foo称为:
uint16_t p = 42;
foo(reinterpret_cast<char*>(&p), 2); // now, we're ok
或:
char data[64];
new (data) uint16_t{42};
foo(data, 2); // also ok, though with C++17 you'll have to use std::launder
但除此之外,它是UB。非UB的方法是:
uint16_t data16;
memcpy(&data16, data, sizeof(data16));
许多编译器将其视为reinterpret_cast
。
也就是说,大量的网络代码正在做你正在做的事情,如果编译器以一种导致它的方式对这些代码进行优化,那么街道上会发生暴乱许多愤怒的消息不做你想要的。
答案 1 :(得分:1)
执行取消引用类型转换指针的任何(除非它只是cv-casted或转换为兼容类型或char)是UB。
这是不正确的。
任何指针都可以转换为char*
和void*
并返回。仅当原始指针的类型与解除引用指针时使用的指针类型不同时,它才是UB。甚至有例外。有关示例,请参阅Struct alignment and type reinterpretation。