[英]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.