以下最简单的代码示例会导致一个警告:
#include <iostream>
#include <climits>
int b = INT_MAX + 1; //warning: overflow in expression; result is -2147483648
//with type 'int' [-Winteger-overflow]
unsigned int a = INT_MAX + 1; //OK
int main()
{
std::cout << b << std::endl << a;
}
为什么第二行溢出不会引起任何警告?这是一个错误,还是我不明白?
答案 0 :(得分:2)
这是一个错误,虽然结果是“正确的”。据我所知,似乎操作实际上在添加操作之前变成了无符号。
警告是由此代码生成的,显然会检查unsigned并跳过溢出检查(明确指出并在评论中说明):
/// Perform the given integer operation, which is known to need at most BitWidth
/// bits, and check for overflow in the original type (if that type was not an
/// unsigned type).
template<typename Operation>
static APSInt CheckedIntArithmetic(EvalInfo &Info, const Expr *E,
const APSInt &LHS, const APSInt &RHS,
unsigned BitWidth, Operation Op) {
if (LHS.isUnsigned())
return Op(LHS, RHS);
APSInt Value(Op(LHS.extend(BitWidth), RHS.extend(BitWidth)), false);
APSInt Result = Value.trunc(LHS.getBitWidth());
if (Result.extend(BitWidth) != Value) {
if (Info.checkingForOverflow())
Info.Ctx.getDiagnostics().Report(E->getExprLoc(),
diag::warn_integer_constant_overflow)
<< Result.toString(10) << E->getType();
else
HandleOverflow(Info, E, Value, E->getType());
}
return Result;
}
我们可以看到,unsigned没有发出警告:
if (LHS.isUnsigned())
return Op(LHS, RHS);
删除程序(删除#includes
,从相关标头复制#define INT_MAX ...
),并使用clang++ -Xclang -ast-dump ...
运行clang,会得到以下输出:
TranslationUnitDecl 0x4ca2830 <<invalid sloc>> <invalid sloc>
|-TypedefDecl 0x4ca2d70 <<invalid sloc>> <invalid sloc> implicit __int128_t '__int128'
|-TypedefDecl 0x4ca2dd0 <<invalid sloc>> <invalid sloc> implicit __uint128_t 'unsigned __int128'
|-TypedefDecl 0x4ca3190 <<invalid sloc>> <invalid sloc> implicit __builtin_va_list '__va_list_tag [1]'
|-VarDecl 0x4ca31f0 <of.cpp:3:1, col:19> col:5 b 'int' cinit
| `-BinaryOperator 0x4ca3288 <line:1:19, line:3:19> 'int' '+'
| |-IntegerLiteral 0x4ca3248 <line:1:19> 'int' 2147483647
| `-IntegerLiteral 0x4ca3268 <line:3:19> 'int' 1
|-VarDecl 0x4ce2280 <line:6:1, col:28> col:14 a 'unsigned int' cinit
| `-ImplicitCastExpr 0x4ce2340 <line:1:19, line:6:28> 'unsigned int' <IntegralCast>
| `-BinaryOperator 0x4ce2318 <line:1:19, line:6:28> 'int' '+'
| |-IntegerLiteral 0x4ce22d8 <line:1:19> 'int' 2147483647
| `-IntegerLiteral 0x4ce22f8 <line:6:28> 'int' 1
`-FunctionDecl 0x4ce23b0 <line:7:1, line:10:1> line:7:5 main 'int (void)'
`-CompoundStmt 0x4ce24a8 <line:8:1, line:10:1>
我们可以清楚地看到它是整数:
| `-BinaryOperator 0x4ce2318 <line:1:19, line:6:28> 'int' '+'
| |-IntegerLiteral 0x4ce22d8 <line:1:19> 'int' 2147483647
| `-IntegerLiteral 0x4ce22f8 <line:6:28> 'int' 1
因此,编译器必须首先转换为无符号,然后应用+
。铸造意味着:
| `-ImplicitCastExpr 0x4ce2340 <line:1:19, line:6:28> 'unsigned int' <IntegralCast>
我将再看一看,看看我是否能找出实际出错的地方。但那将需要等待一段时间......