cppcoreguidelines-narrowing-conversions

检查隐式缩窄转换,例如:int i = 0; i += 0.1;。虽然在这个例子中问题很明显,但在以下情况下可能就不是那么明显了:void MyClass::f(double d) { int_member_ += d; }

此检查实现了 C++ Core Guidelines 中的 ES.46

我们只强制执行指南的一部分,更具体地说,我们标记从
  • 整数到更窄的整数(例如 charunsigned char)的缩窄转换,如果设置了 WarnOnIntegerNarrowingConversion 选项,

  • 整数到更窄的浮点数(例如 uint64_tfloat)的缩窄转换,如果设置了 WarnOnIntegerToFloatingPointNarrowingConversion 选项,

  • 浮点数到整数(例如 doubleint),

  • 浮点数到更窄的浮点数(例如 doublefloat)的缩窄转换,如果设置了 WarnOnFloatingPointNarrowingConversion 选项。

此检查将标记
  • 所有没有用显式转换(c 样式或 static_cast)标记的缩窄转换。例如:int i = 0; i += 0.1;void f(int); f(0.1);

  • 所有使用缩窄转换的二元运算符的应用。例如:int i; i+= 0.1;

选项

WarnOnIntegerNarrowingConversion

当为 true 时,检查将警告整数缩窄转换(例如 intsize_t)。默认值为 true

WarnOnIntegerToFloatingPointNarrowingConversion

当为 true 时,检查将警告整数到浮点数的缩窄转换(例如 size_tdouble)。默认值为 true

WarnOnFloatingPointNarrowingConversion

当为 true 时,检查将警告浮点数缩窄转换(例如 doublefloat)。默认值为 true

WarnWithinTemplateInstantiation

当为 true 时,检查将在模板实例化中警告缩窄转换。默认值为 false

WarnOnEquivalentBitWidth

当为 true 时,检查将警告在具有等效位宽的类型之间进行转换时出现的缩窄转换。(例如 int n = uint(0);long long n = double(0);) 默认值为 true

IgnoreConversionFromTypes

将忽略从此分号分隔列表中的任何类型进行的缩窄转换。这对于剔除常见的但不太常见的问题赋值可能很有用,例如 int n = std::vector<char>().size();int n = std::difference(it1, it2);。默认列表为空,但对于遗留代码库,一个建议的列表是 size_t;ptrdiff_t;size_type;difference_type

PedanticMode

当为 true 时,即使浮点值在目标类型中完全可表示,检查也会警告将浮点常量分配给整数值(例如 int i = 1.0;)。默认值为 false

常见问题解答

  • “从 ‘int’ 到 ‘float’ 的缩窄转换”是什么意思?

IEEE754 浮点数可以表示范围 [-2^PrecisionBits, 2^PrecisionBits] 内的所有整数值,其中 PrecisionBits 是尾数中的位数。

对于 float,这将是 [-2^23, 2^23],其中 int 可以表示范围 [-2^31, 2^31-1] 内的值。

  • “实现定义的”是什么意思?

您可能遇到过类似“从 ‘unsigned int’ 到有符号类型 ‘int’ 的缩窄转换是实现定义的”的消息。C/C++ 标准没有为有符号整数规定二进制补码,因此编译器可以自由定义将无符号整数转换为有符号整数的语义。Clang 的实现使用二进制补码格式。