是numeric_limits< int> :: is_modulo从逻辑上矛盾
Is numeric_limits<int>::is_modulo logically contradictory?
在另一个问题中,std::numeric_limits<int>::is_modulo
的主题出现了。但是我考虑的越多,似乎规格或GCC或两者都出现了问题。
让我从一些代码开始:
#include <limits>
#include <iostream>
bool test(int x)
{
return x+1 > x;
}
int main(int argc, char *argv[])
{
int big = std::numeric_limits<int>::max();
std::cout << std::numeric_limits<int>::is_modulo << " ";
std::cout << big+1 << " ";
std::cout << test(big) << "n";
}
当我用g++ -O3 -std=c++11
(X86_64 GCC 4.7.2)编译此内容时,它会产生以下输出:
1 -2147483648 1
也就是说, is_modulo
是正确的,一个加上 INT_MAX
是负的,一个加上 INT_MAX
大于 INT_MAX
。
如果您是那种有任何回答这个问题的现实机会的人,那么您已经知道这里发生了什么。C 规范说整数溢出是不确定的行为。允许编译器假设您不这样做;因此,对x+1
的论点不能是INT_MAX
;因此,编译器可以(并将)编译test
函数以无条件返回true
。到目前为止,一切都很好。
但是,C 11规格也说(18.3.2.4段60-61):
static constexpr is_modulo;
true如果类型为模拟。222如果任何操作,则类型为modulo 涉及
+
,-
或*
的该类型的值将其结果的值 落在范围内[min(),max()]
之外,值返回的值有所不同 来自max() - min() + 1
的整数倍数的真实值。在大多数机器上,这是浮动类型的
false
,true
用于 未签名的整数和签名整数的true
。
请注意,第5款(4)仍然读到:"如果在评估表达式期间,该结果在数学上未定义或不在其类型的代表值范围内,则行为是未定义的。"没有提及is_modulo == true
创建异常。
因此,在我看来,标准在逻辑上是矛盾的,因为整数溢出不能同时定义和未定义。或至少,GCC不合格,因为它具有is_modulo
为true
,即使签名算术最肯定不会缠绕。
是标准越野车吗?GCC不合格吗?我想念什么吗?
如果 is_modulo
是签名类型的 true
(例如 int
),而通常由通常的算术转换而没有变化,那么对于零除零以外的任何算术操作,零都有一个正确的结果(数学)整数将模块映射到类型范围内的单个值,因此实现被限制为行为,好像实际结果是类型范围的真实结果。因此,如果实现要保留溢出算术,则必须将is_modulo
设置为false
。
在GCC邮件列表中讨论了 adaauseam ,然后在PR 22200下,最终结论is_modulo
的值应为签名类型的CC_28的值;更改是在今年4月对LibstDC 进行的。
请注意,在C 03中,语言有显着不同:
18.2.1.2 Numeric_Limits成员[lib.numeric.limits.members]56 - [...]如果可以添加两个正数,则类型为模型,并具有结果 缠绕到第三个数字。
鉴于有可能使用不确定的行为是可能的,因此可以说libstdc 的先前行为(具有is_modulo
作为true
)是正确的,并且与G 的行为一致。应考虑到有关链接的PR的较早讨论。
- Why is UINT32_MAX + 1 = 0?
- C++错误:"error: int aaa::bbb is protected within this context"
- 创建具有 new in 函数和"this is nullptr"异常的对象
- 使用 cmake 的 Linux 终端上的"Conversion to non-scalar type is requested"错误
- Is !NaN not a NaN?
- Directx 11 - CompileFromFile() is not compiling
- Centos7 g++ "to_string is not in a member of std"
- "Unable to start debugging. No process is associated with this object." - 在Visual Studio Code中使用GDB
- Where is std::hardware_destructive_interference_size?
- 将成员函数作为构造函数参数调用时出错 "Variable is not a type name"
- What is unordered_set in C++
- 你如何理解"std: :forward is just syntactic sugar"?这是真的吗?
- C++ "error: use of overloaded operator '*' is ambiguous"似乎只有一场比赛
- C++ is calculating wrong
- Is it good to use SDL_PIXELFORMAT_UNKNOWN?
- reference_wrapper导致"incomplete type is not allowed"
- 为什么即使在定义之后仍存在"Identifier is undefined error "?
- 结构中的错误"Incomplete type is not allowed"
- Crash in boost::archive::text_iarchive in_archive {is} boost
- 在反转字符串'my.name.is'时,我得到的输出为"is@.name.my"。我不明白'@'是从哪里来的