4

我一直在阅读一本书(C++ Programming Language Stroustrup 4th ed)。与初始化相关的部分中给出的示例如下:

void f(double d, int i)
{
    int a{ d };     // error : possible truncation
    char b{ i };    // error : possible narrowing
}

截断和缩小之间究竟有什么区别?

4

4 回答 4

6

缩小转换基本上是任何可能导致信息丢失的转换。严格来说,缩小转换是:

隐式转换

  • 从浮点类型到整数类型,或
  • 从 long double 到 double 或 float,或从 double 到 float,除非源是常量表达式并且转换后的实际值在可以表示的值范围内(即使不能精确表示),或
  • 从整数类型或无作用域枚举类型到浮点类型,除非源是常量表达式并且转换后的实际值将适合目标类型并且在转换回原始类型时将产生原始值,或
  • 从整数类型或无作用域枚举类型到不能表示原始类型的所有值的整数类型,除非源是常量表达式,其值在整数提升后将适合目标类型,或
  • 从指针类型或指向成员的指针类型到 bool。

请注意,这意味着您发布的两个转化都在缩小转化范围。int a{ d };是第一种情况,char b{ i };是第四种情况。

截断仅在浮点类型和整数类型之间转换时发生。它通常是指丢失的浮点数的小数部分(来源)。这意味着截断是缩小转换的子集。

于 2020-04-08T17:26:24.823 回答
3

截断和缩小之间究竟有什么区别?

截断将诸如 afloat或 a之类的基于十进制的值缩短double为其整数形式int,并删除了小数点后的额外精度位(从相应的十进制形式中的 2 -1开始)。

Adouble也可以被截断为 a float,可能会发生溢出(取决于值的大小)并以二进制形式删除一半的精度位(因为 double 的精度是 float 的两倍,通常为 64和 32 位浮点数)。

对于double被截断为 a的示例float,请考虑至少超过 23 个精度位(考虑浮点数的尾数)的东西,例如 PI 的值,BenVoigt 在评论中给出了一个示例。

由 double 给出的 PI 值为:

11.001001000011111101101010100010001000010110100011000
// 3.141592653589793116

请注意,有 52 个精度位(根据 IEEE 754 标准,从 0 到 51),或形成小数点后值的位。

对应的截断浮点值:

11.0010010000111111011011
// 3.1415927410125732422

请注意 PI 值相对于上述数字的不准确性。这是由于在截断值 from doubleto float(从 0 到 22 只有 23 个精度位)时删除了精度的尾随位,在这种情况下通常会降低精度位。

在将浮点值转换为整数形式之后,您可以说它的行为类似于floor函数调用。

顾名思义,缩小就是缩短值,但与截断不同,它不限于将浮点值缩短为整数值。它也适用于其他转换,例如 along到 an int,指针类型到布尔值和字符到整数(如您的示例中所示)。

于 2020-04-08T17:35:19.663 回答
1

也许最好用一个例子来理解......

可以说d == 3.1415926,然后在您的代码a中将最终为3. 那就是截断。

另一方面,如果i == 1000则超出 的范围char。如果charunsigned值将环绕,您将获得1000%256的值b。发生这种情况是因为int具有比 更宽的范围char,因此这种转换称为窄化。

于 2020-04-08T17:23:46.213 回答
0
double d=2.345;
int a = d; // a is 2 now, so the number 2.345 is truncated

至于intto charchar大小为 1 个字节,而int有 4 个字节(假设为 32 位),因此您将“缩小”变量i

可能只是英语:) 您可以在字典中查找单词,这样可能会更清楚。

于 2020-04-08T17:21:19.553 回答