簡體   English   中英

在C / C ++中允許有符號整數溢出

[英]Allowing signed integer overflows in C/C++

希望簽名整數在它們變得太大時溢出。 如何在不使用下一個最大數據類型的情況下(或者當我已經在int128_t時)實現這一目標?

例如,使用8位整數19 * 12通常為260,但我希望結果為1 11 10 01 00 ,第9位被截止,因此為-27。

簽名溢出在C中是未定義的, 這是真實的

一個解決方案如下

signed_result = (unsigned int)one_argument + (unsigned int)other_argument;

上述解決方案涉及從unsignedint的最終轉換中的實現定義行為,但不調用未定義的行為。 對於大多數編譯平台的實現定義選擇,結果正是您期望的兩個補碼結果。

最后, 針對實現定義的選擇迫使編譯器為您提供所期望的行為的眾多平台之一的優化編譯器將上述代碼編譯為明顯的匯編指令。

或者,如果您正在使用gcc,那么選項-fwrapv / -fno-strict-overflow可能正是您想要的。 它們提供了有關簽名溢出的標准的額外保證。 我不確定兩者之間的區別。

根據C和C ++標准,未定義有符號整數溢出。 沒有特定的平台,沒有辦法實現你想要的。

您可以在int周圍創建一個目標包裝器,但這將涉及相當多的開銷代碼。

聽起來你想要做一些未編組的整數運算,然后將結果填充到有符號整數中:

unsigned char a = 19;
unsigned char b = 12;

signed char c = (signed char)(a*b);

應該給你你想要的東西。 如果沒有,請告訴我們。

假設有兩個補碼有符號整數運算(這些天是合理的假設),對於加法和減法,只需轉換為無符號進行計算。 對於乘法和除法,確保操作數為正,轉換為無符號,計算和調整符號。

這是可能做到這一點在一個正確的標准C的方式,只要你有機會獲得一個unsigned類型,它是相同的寬度為您的signed類型(即,有一個更大的價值位)。 int64_t演示:

int64_t mult_wrap_2scomp(int64_t a, int64_t b)
{
    uint64_t result = (uint64_t)a * (uint64_t)b;

    if (result > INT64_MAX)
        return (int64_t)(result - INT64_MAX - 1) - INT64_MAX - 1;
    else
        return (int64_t)result;
}

這不會產生任何有問題的中間結果。

使用更大的數據類型。 使用GMP,您將擁有您可能需要的所有空間。

暫無
暫無

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

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