使用reinterpret_cast签名混叠
Signedness aliasing using reinterpret_cast
采取以下代码
#include <iostream>
void func() {
int i = 2147483640;
while (i < i + 1)
{
std::cerr << i << 'n';
++i;
}
return;
}
int main() {
func();
}
此代码显然是错误的,因为只有在签名的int i
溢出(即UB(时才可以终止循环,因此,编译器可以例如将其优化到无限的循环中(Clang在-O3
上使用(,或者做其他编译器各种时髦的东西。我现在的问题是:从我对C 标准的读取中,等于签名的类型 May 别名(即Pointers int*
和unsigned*
May May May(。为了进行一些时髦的签名"包装",以下行为是否不确定?
#include <iostream>
static int safe_inc(int a)
{
++reinterpret_cast<unsigned&>(a);
return a;
}
void func() {
int i = 2147483640;
while (i < safe_inc(i))
{
std::cerr << i << 'n';
++i;
}
return;
}
int main() {
func();
}
我在-O3
上使用-Wall -Wextra -Wpedantic -O3 -fsanitize=address,undefined
参数的Clang 8和GCC 9尝试了上述代码,并且没有任何错误或警告,并且循环在包装到INT_MIN
后终止。
cppreference.com告诉我
类型aleiasing
每当尝试通过类型AliasedType的glvalue读取或修改类型Dynamictype对象的存储值时,该行为是不确定的,除非以下一个是正确的:
- AliasedType是Dynamictype的签名或未签名的变体(可能是CV合格的(。
从我的阅读中,这意味着出于类型混叠的目的,不考虑签名,并且使用reinterpret_cast
的代码具有明确的语义(尽管有些俗气(。
在这里混音是完全合法的。请参阅http://eel.is/c draft/expr.prop#basic.lval-11.2:
如果程序试图通过一个与其中之一的Glvalue([Cons.Qual](的类型不相似([Cons.Qual](以下类型的行为不确定:53
(11.1(对象的动态类型
(11.2(a 类型是签名或无符号类型对应于对象的动态类型
我认为,也值得谈论实际的溢出问题,这不一定需要reinterpret_cast
。通过隐式积分转换
unsigned x = i;
++x;
i = x; // this would serve you just fine.
此代码将是实现定义的pre-c 20,因为您将从无法用目标类型表示的值转换。
由于C 20此代码将被很好地形成。
请参阅https://en.cppreference.com/w/cpp/language/implitic_conversion
在旁注上,如果要整数溢出语义,则不妨从未签名类型开始。
您的代码完全合法,CPP参考是一个很好的来源。您可以在标准[basic.lval]/11
中找到相同的信息如果程序试图通过glvalue访问对象的存储值,该glvalue的类型与以下类型不相似([cons.qual](,则行为不确定:
对象的动态类型
一种类型是对象的动态类型的签名或无符号类型,[...]
- 如何理解C++标准N3337中的expr.const.cast子句8
- C++Cast运算符过载
- 错误:"cast"未命名类型void setCastDescription(std::string
- 通过使用 const-cast 的非常量引用来延长临时的寿命
- "(void) cast"与功能有什么区别 "__attributes__"来沉默未使用的参数警告?
- C++:"Expected '(' for function-style cast or type construction"错误
- 为什么选择 g++ 给予者:"error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast]"
- Gtk+ g_signal_connect() 和 C++ lambda 会导致"invalid cast"错误
- Shared_ptr cast vs static_cast speed
- C++20 中的严格别名规则是否允许标准 c++ unicode 字符和下划线类型之间"reinterpret
- 在 iOS 上使用 Aruco 构建 OpenCV 时"Functional-style cast from id to double is not allowed"
- 覆盖 CAST 运算符(我认为它被称为向下转换)
- C++错误,隐 <function-style-cast> 式要求使用模板化类一次调用多个构造函数的多个转换
- 如何修复<function-style-cast>错误:无法从'initializer list'转换为asdending比较<W>(模板函子)
- C++ C++ 中的函数声明,键入 CAST
- static_cast会丢弃错误,但C风格的演员cast有效
- C++ cast char * to unsigned char
- 禁用 Clang 中的"cast from pointer to smaller type uint32_t"错误
- 是否可以使用gcc 3.3版修复与int*cast相关的Sun Solaris OS 5.8分段故障
- C++ const-cast 一个引用