簡體   English   中英

帶符號的長整數隨着它的增長而變為負數?

[英]Signed long integer becomes negative as it grows?

我正在做一些數學運算,然后打印一個有符號的長整數,如下所示:

在file1.c

#include <stdio.h>

int main (int argc, char *argv[])
{
    long my_signed_integer = 9999L * 9999L * 9999L * 9999L;
    printf("This is my signed integer %ld.\n", my_signed_integer); 

    return 0;
}

Makefile文件

CFLAGS=-Wall -g

all: file1

clean:
    rm -f file1

我試圖看看沒有我的編譯器給我一個錯誤,每次添加一個9999L到乘法,然后運行:

make
./file1.c

看看會發生什么。


4次

當使用9999L 4次時(如上例所示),我得到:

This is my signed integer 9996000599960001.

沒有任何警告。


5次

使用9999L 5次,我得到1個警告:

warning: overflow in expression; result is 7716289630452291919 with type 'long'
      [-Winteger-overflow]

但該文件仍然編譯,最終結果是:

This is my signed integer 7716289630452291919.


6次

使用9999L 6次,我得到2個警告 - 一個帶負數:

warning: overflow in expression; result is 7716289630452291919 with type 'long'
      [-Winteger-overflow]
        long my_signed_integer = 9999L * 9999L * 9999L * 9999L * 9999L * 9999L;
                                                               ^
warning: overflow in expression; result is -7550445434587511647 with type 'long'
      [-Winteger-overflow]
        long my_signed_integer = 9999L * 9999L * 9999L * 9999L * 9999L * 9999L;

唉,文件仍然編譯,結果是:

This is my signed integer -7550445434587511647.


隨着我添加越來越多的整數,這種模式仍在繼續 - 我每次都會收到另一個警告。

首先,有人可以解釋為什么編譯器不會崩潰並拒絕編譯文件? 顯然有溢出 - 為什么這是容忍的,而其他情況 - 例如乘以非常大的數字 - 會讓它崩潰?

另外,為什么最終結果是負整數?

根據C標准,有符號整數類型的溢出是未定義的行為 因此編譯器可以自由地生成它想要的任何行為。 這也意味着可以自由地生成警告。

實際上,在使用2的整數補碼表示的托管實現上,溢出的行為就好像參數是無符號的(因此減少的模2 ^(位長))並且結果被解釋為有符號。

在您的特定情況下,似乎long是64位類型。 因此,將9999L自身乘以4次適合該類型,但更多並且您已經溢出。 您獲得的值是解釋為有signed long整數的結果的最低64位。

在5次的情況下,高階位碰巧沒有被設置,因此結果顯示為正。 在6次的情況下,高位被設置,因此它顯示為負。

暫無
暫無

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

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