#AB05. 挂分经典错误1

挂分经典错误1

当前没有测试数据。

1. 函数该返回时不返回

void 类型函数,如果没有返回对应类型的值,DevC++ 可以正常运行,但是 OJ 和比赛评测环境都会直接爆零。

2. 精度不够的 double

众所周知,比赛环境中 double 类型占 个字节,和 long long 一样。所以显然无法精确储存 long long 范围的所有数。

而有很多表达式因为是 double,常常导致精度损失而丢失分数:

  • 1e18+1:转成 long long 后值会是
  • 0.1+0.2:值会是 0.30000000000000004,所以 0.1 + 0.2 != 0.3
  • sqrt():默认返回值是 double
  • pow():默认返回值是 double
  • log2():默认返回值是 double

3. 窄化转换

下面这段代码展现了一些爆 惨剧。

#include<bits/stdc++.h>
using namespace std;
struct Num{
    int x;
}; 
Num a;
int main(){
    a = {1e18};
    cout<<"Hello World";
    return 0;
}

这个代码可以在 DevC++ 中成功运行(伴随着一些警告),但是会在正式比赛中直接得到编译错误。这是因为大括号初始化不允许窄化转换,绝大多数版本的编译器下都会得到编译错误,而在某些编译器版本下(比如 DevC++ 的 4.9.2 版本)中只会警告。

窄化转换

在C++中,窄化转换(narrowing conversion)是一种潜在的不安全的数值转换,其中目标类型可能无法保存源类型的所有值。

以下转换被定义为窄化转换:

  • • 从浮点类型到整型。
  • • 从浮点类型到级别较窄或较低的浮点类型,除非要转换的值是constexpr并且在目标类型的范围内(即使目标类型的精度不足以存储数字的所有有效数字)。
  • • 从整数类型转换为浮点类型,除非要转换的值是constexpr,并且其值可以精确存储在目标类型中。
  • • 从整型转换为不能表示原始类型的所有值的另一整型,除非要转换的值是constexpr,并且其值可以精确存储在目标类型中。这包括从宽到窄的整数转换,以及整数符号转换(有符号到无符号,反之亦然)。
  • • 在大多数情况下,隐式窄化转换将导致编译器警告,但有符号/无符号转换除外(根据编译器的配置方式,这可能会产生警告,也可能不会产生警告)。

应尽可能避免窄化转换,因为它们可能不安全,是潜在错误的来源。

大括号初始化不允许窄化转换,除少数几个版本的编译器外,都会得到编译错误。