簡體   English   中英

unsigned int /有符號int / long long:莫名其妙的輸出

[英]unsigned int / signed int / long long: inexplicable output

所以我在玩各種類型,然后在下面得出了這個奇怪的結果。 對其進行調試沒有任何意義,然后唯一的結果就是檢查c ++點,但並沒有太大幫助。 我想知道您是否確切知道這里發生了什么,是否是32Bit和/或64Bit特定問題。

#include <iostream>
using namespace std;

int main() {
    unsigned int u = 1;
    signed int i = 1;

    long long lu = -1 * u;
    long long li = -1 * i;

    std::cout<<"this is a weird " << lu << " " << li << std::endl;

    return 0;
}

輸出在哪里

this is a weird 4294967295 -1

關鍵的觀察結果是表達式-1 * u的類型為unsigned int 這是因為算術轉換的規則*指出,如果一個操作數是unsigned int ,而另一個是有signed int ,則后一個操作數將轉換unsigned int 算術表達式最終僅針對齊次操作數定義,因此轉換發生在適當的運算之前。

-1unsigned int的轉換結果是一個很大的正數,可以表示為long long int ,這是您在輸出中看到的數字。

當前是[expr] /(11.5.3)。

評價

-1 * i

是兩個int類型的平凡乘法:那里沒有什么奇怪的。 並且很long long必須能夠容納任何int


首先要注意的是,C ++中沒有否定文字。

-1 * u

由於運算符的優先級,其值為(-1) * u (-1)的類型必須為int 但這將由於C ++的參數轉換規則而被轉換為unsigned int因為另一個參數是unsigned int 。這樣做是對UINT_MAX + 1模轉換,因此最終將UINT_MAX乘以1,這就是您觀察到的數字,盡管已轉換為long long類型。

最后要注意,這個轉換的行為是受到來自一個轉換規則unsignedsigned類型:如果unsigned intlong long是你的平台上都為64位,則行為是實現定義的。

-1的類型為有signed int 當您在不同基本類型的對象之間執行算術運算時,將轉換一個或兩個參數,以使兩者具有相同的類型。 (對於非基本類型,混合操作數可能會有運算符重載)。 在這種情況下,將遵循轉換規則將有符號值轉換為無符號值。

因此, -1被轉換為無符號。 但是負數不能用無符號類型表示。 發生的結果是,結果值將是可以由無符號類型表示的最小正值,即與原始有符號值一致,而無符號類型可以表示的最大值與之相等。 您平台上的哪個恰好是4294967295。


規則([expr],標准草案):

適用於非整數的規則

否則,應在兩個操作數上執行整數提升(4.5)。61然后,以下規則應應用於提升的操作數:

—如果兩個操作數具有相同的類型,則無需進一步轉換。

—否則,如果兩個操作數都具有符號整數類型或都具有無符號整數類型,則應將具有較小整數轉換等級的操作數轉換為具有較大等級的操作數的類型。

—否則,如果具有無符號整數類型的操作數的秩大於或等於另一個操作數的類型的秩,則應將具有符號整數類型的操作數轉換為具有無符號整數類型的操作數的類型。 (這適用於您的情況)

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

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

位模式“ 0xFFFFFFFF”在解釋為32b有符號整數時與“ -1”相對應,在解釋為32b無符號整數時與“ 4294967295”相對應。

  • 如果使用-2,則結果為“ 4294967294”
  • 如果使用-3,則結果為“ 4294967293”
  • 如果使用-4,則結果為“ 4294967292”
  • ....

暫無
暫無

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

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