簡體   English   中英

添加超過0xFFFFFFFF的有符號整數

[英]Adding an signed integer beyond 0xFFFFFFFF

#include <stdio.h>

void fun3(int a, int b, int c)
{
   printf("%d \n", a+b+c );
}
void fun2 ( int x, int y)
{
   fun3(0x33333333,0x30303030, 0x31313131);
   printf("%d \n", x+y);
}
fun1 (int x)
{
   fun2(0x22222222,0x20202020);
   printf("%d  \n", x);
}
main()
{
  fun1(0x1111111);
}

我正在通過上面的程序進行堆棧破壞。 我正在使用某些不希望的值獲取上述程序的o / p。 我所能理解的是,如果相加的值超出0xFFFFFFFF,則較小的負整數變為最大值,即-1變為0xFFFFFFFF。 關於此的任何見解

到@Cornstalks的要點: INT_MIN0x80000000(int)-1為2的補碼(無論如何在32位系統上(int)-10xFFFFFFFF

這使指令集可以執行帶符號算術的操作,例如:

1 + -2 = -1

成為(為簡短起見,以符號short開頭)

0x0001 + 0xFFFE = 0xFFFF

... 然后:

1 + -1 = 0

在內部以溢出表示為

0x0001 + 0xFFFF = 0x0000

另外,@ Cornstalks指出:內部表示(以及溢出添加)是實現細節。 C實現(和指令集)不需要用2的補碼表示整數,因此為有符號整數類型提供十六進制值可能會使您陷入C實現的子集。

編輯(更正) (我錯過了要點。我的答案是對常數的,但問題包含函數的參數,那么這里發生的是有符號整數對象的溢出,並且正如他的注釋中正確指出的@Cornstalks一樣,這是未定義的行為)。 /編輯

fun1()您以錯誤的方式使用了printf()
您編寫了"%d"以接受一個int ,但是如果您的數字大於MAX_INT ,則情況並非如此。

您必須檢查系統中的MAX_INT的值。
如果您以十六進制格式編寫整數常量,則標准C(ISO C99或C11)將按照以下順序嘗試將值放入該常量可以容納的第一種類型:

int,unsigned int,long int,unsigned long int,long long int,unsigned long long int。

因此,如果您的常數大於MAX_INTint范圍內的最大值),則您的常數(如果為正)的類型為unsigned int ,但指令%d期望有signed int值。 因此,將示出一些負數。

最糟糕的是,如果常量的值大於UMAX_INTunsigned int范圍內的unsigned int ),則常量的類型將是long int, unsigned long int, long long int ,其精度嚴格大於of unsigned int
這意味着%d變成一個錯誤的指令。

如果您不能完全確定自己的值將是多少,可以將其強制轉換為最大的整數類型:

  printf("%lld", (long long int) 0x33333333333);

指令%lld表示long long int
如果您始終對正值感興趣,則必須使用%llu並將其%lluunsigned long long int

  printf("%llu", (unsigned long long int) 0x33333333333);

通過這種方式,你避免了“搞笑”的數字,高達,你看大號碼不丟失任何精度。

備注:常量INT_MAXUINT_MAX等位於limits.h中

重要提示:管型的自動順序僅適用於八進制和十六進制常量。 對於十進制常量,還有另一條規則:

int,long int,long long int。

fun3將嘗試打印值0x94949494。 這大於最大的4個字節的整數值0x7FFFFFFF,因此它將“溢出”,並且(如果在今天制造的幾乎每台計算機上,)我都會正確生成負數-0x6B6B6B6C(如果我正確地做了算術的話),即-1802201964。

fun1fun2應該顯示“預期”的積極結果。

暫無
暫無

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

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