簡體   English   中英

C++ 隱式轉換(有符號 + 無符號)

[英]C++ Implicit Conversion (Signed + Unsigned)

我明白,關於隱式轉換,如果我們有一個無符號類型操作數和一個有符號類型操作數,並且無符號操作數的類型與有符號操作數的類型相同(或大於),則有符號操作數將被轉換未簽名。

所以:

unsigned int u = 10;  
signed int s = -8;

std::cout << s + u << std::endl;

//prints 2 because it will convert `s` to `unsigned int`, now `s` has the value
//4294967288, then it will add `u` to it, which is an out-of-range value, so,
//in my machine, `4294967298 % 4294967296 = 2`

我不明白的是 - 我讀到如果有符號操作數的類型大於無符號操作數:

  • 如果無符號類型中的所有值都適合較大類型,則無符號操作數將轉換為有符號類型

  • 如果無符號類型中的值不適合較大類型,則有符號操作數將轉換為無符號類型

所以在下面的代碼中:

signed long long s = -8;
unsigned int u = 10;
std::cout << s + u << std::endl;

u將被轉換為signed long long 因為int 值可以放入signed long long 中??

如果是這種情況,在什么情況下較小的類型值不適合較大的類型值?

標准中的相關引述:

5 表達式 [expr]

10 許多期望算術或枚舉類型操作數的二元運算符會以類似的方式導致轉換和產生結果類型。 目的是產生一個通用類型,它也是結果的類型。 這種模式稱為通常的算術轉換,其定義如下:

[關於等號類型或等號類型省略的2個子句]

— 否則,如果具有無符號整數類型的操作數的秩大於或等於另一個操作數的類型的秩,則將具有符號整數類型的操作數轉換為具有無符號整數類型的操作數的類型。

— 否則,如果有符號整數類型操作數的類型可以表示無符號整數類型操作數類型的所有值,則將無符號整數類型操作數轉換為有符號整數類型操作數的類型。

— 否則,兩個操作數都應轉換為與帶符號整數類型的操作數類型對應的無符號整數類型。

讓我們為上述 3 個子句中的每一個考慮以下 3 個示例案例,其中sizeof(int) < sizeof(long) == sizeof(long long) (很容易適應其他情況)

#include <iostream>

signed int s1 = -4;
unsigned int u1 = 2;

signed long int s2 = -4;
unsigned int u2 = 2;

signed long long int s3 = -4;
unsigned long int u3 = 2;

int main()
{
    std::cout << (s1 + u1) << "\n"; // 4294967294
    std::cout << (s2 + u2) << "\n"; // -2 
    std::cout << (s3 + u3) << "\n"; // 18446744073709551614  
}

帶有輸出的實時示例

第一個子句:相等等級的類型,因此有signed int操作數轉換為unsigned int 這需要一個值轉換(使用二進制補碼)給出 te 打印值。

第二條:有符號類型有更高的等級,並且(在這個平台上!)可以表示無符號類型的所有值,所以無符號操作數轉換為有符號類型,你得到-2

第三個子句:signed 類型再次有更高的等級,但是(在這個平台上!)不能代表 unsigned 類型的所有值,所以兩個操作數都被轉換為unsigned long long ,並且在對有符號操作數進行值轉換后,你得到印刷價值。

請注意,當無符號操作數足夠大(例如在這些示例中為 6)時,由於無符號整數溢出,所有 3 個示例的最終結果將為 2。

(已添加)請注意,當您對這些類型進行比較時,您會得到更多意想不到的結果。 讓我們考慮上面帶有<示例 1:

#include <iostream>

signed int s1 = -4;
unsigned int u1 = 2;
int main()
{
    std::cout << (s1 < u1 ? "s1 < u1" : "s1 !< u1") << "\n";  // "s1 !< u1"
    std::cout << (-4 < 2u ? "-4 < 2u" : "-4 !< 2u") << "\n";  // "-4 !< 2u"
}

由於u后綴顯式地使2u unsigned ,因此適用相同的規則。 結果可能不是您在用 C++ -4 < 2u編寫時比較-4 < 2時所期望的......

signed int不適合unsigned long long 所以你會有這個轉換: signed int -> unsigned long long

請注意,C++11 標准在這里不討論較大或較小的類型,而是討論具有較低或較高等級的類型。

考慮long intunsigned int ,它們都是 32 位。 long int的等級高於unsigned int ,但由於long intunsigned int都是 32 位,因此long int不能表示unsigned int所有值。

因此我們陷入了最后一種情況(C++11:5.6p9):

  • 否則,兩個操作數都應轉換為與帶符號整數類型的操作數類型對應的無符號整數類型。

這意味着long intunsigned int都將轉換為unsigned long int

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM