C++ 表示式中的型別轉換

lih627發表於2020-11-29

C++ 表示式中的型別轉換

簡介

最近刷題經常遇到對結果取模,由於某些操作導致溢位。例如 MOD = 10e9 + 7

下列表示式

int hash = (base * base) % MOD // base * base  溢位

需要在表示式中加入強制型別轉換。摘抄C++ Primer Plus 3.4.4 型別轉換章節之表示式中的轉換。

自動轉換

整形提升(integral promotion): C++ 在計算表示式時,自動將 bool char unsigned char singed char short 轉換為int。 例如true->1。由於int 是計算機最自然的型別,計算速度可能最快。

在表示式中,編譯器通過按順序查表進行轉換:

  1. 如果一個運算元型別是 long double,將另一個運算元轉換為long double
  2. 否則,如果一個運算元是double,將另一個運算元轉換為double
  3. 否則,如果一個運算元是float,將另一個運算元轉換為float
  4. 否則,說明運算元都是整型,執行整型提升
  5. 兩個運算元均為有符號整型或者均為無符號整型,將級別低的轉換成級別高的型別
  6. 如果兩個運算元其中一個有符號整型另外一個無符號整型,且無符號整型級別比有符號運算元級別高,將有符號運算元轉換為無符號運算元所屬的型別
  7. 否則,如果有符號型別可表示無符號型別的所有可能取值,將無符號運算元轉換為有符號運算元所屬的型別
  8. 否則,將兩個運算元都轉換為有符號型別的無符號版本。

例如:對於 char + unsigned int 或者unsigned char + char ,執行4

對於6例如 unsigned long long + int 程式碼如下

#include <iostream>
#include <cmath>
#include <limits>
int main()
{
    using namespace std;
    cout << "size of int:" << sizeof(int) << endl;
    cout << "size of unsigned long long:" << sizeof(unsigned long long) << endl;
    int a = INT_MAX;
    cout << "MAX " << INT_MAX << endl;
    unsigned long long b = INT_MAX * 2ll; // 這裡用到了5
    auto ret = a + b;
    cout  << ret << " " << sizeof(ret) << endl;
    return 0;
}
/*
size of int:4
size of unsigned long long:8
MAX 2147483647
*/

對於7,例如long long + unsigned int 程式碼如下

#include <iostream>
#include <cmath>
#include <limits>
int main()
{
    using namespace std;
    cout << "size of unsigned int:" << sizeof(unsigned int) << endl;
    cout << "size of long long:" << sizeof(long long) << endl;
    unsigned int a = 0xffffffff; // unsigned 最大值
    cout << "MAX " << a << endl;
    long long b = INT_MAX * 2ll;
    auto ret = a + b;
    cout  << ret << " " << sizeof(ret) << endl;
    return 0;
}
/*
size of unsigned int:4
size of long long:8
MAX 4294967295
8589934589 8
*/

強制型別轉換

可以通過如下兩種方式實現

(typeName) value // (long long )1
typeName (value) // long long (1)

總結

顯然對於開始的例子,可以通過

using ll = long long;
int hash = ll(base) * base % MOD

解決

相關文章