2013-07-30 34 views
3

我知道〜操作符不能操作。但我無法確定下列程序的輸出(即-65536)。究竟發生了什麼?不對整數值進行操作

#include <stdio.h> 

int main(void) { 
    int b = 0xFFFF; 
    printf("%d",~b); 
    return 0; 
} 
+1

所以你已經知道它到底是什麼,你的問題比 – aaronman

+2

@suspectus請不要將C標籤添加到C++標籤的問題,反之亦然。這些是不同的語言。如果您認爲問題是C而不是C++,並且標記爲C++錯誤,那麼在添加C標記時應該刪除C++標記。 – Dukeling

+0

@aaronman如果它不是'b',那麼輸出應該是0,但是爲什麼-65536 –

回答

4

當您將16位值0xffff分配給32位整數b時,變量b實際上變爲0x0000ffff。這意味着當您執行按位補碼時,它變爲0xffff0000,它與小數點-65536相同。

1

C++中的〜運算符是位運算符NOT運算符。它也被稱爲按位補碼。這是翻轉你的簽名的整數的位。

舉例來說,如果你有

int b = 8; 
// b in binary = 1000 
// ~b = 0111 

這將翻轉,表示爲初始整數位。

+0

〜b = 0111只有int是4位。它最有可能是1111111111110111二進制,假設32位整數 – franji1

+0

沒錯,但他沒有提供任何有關架構的信息 –

-1

對於整數每一個二進制數,按位非運算變爲全1變成0,和全0變爲1秒。

所以十六進制0xFFFF是二進制1111 1111 1111 1111(每個十六進制字符是4位,和F,爲15,是所有四位全爲1)

您設置一個32位整數的是,這意味着它的現在:

0000 0000 0000 0000 1111 1111 1111 1111

然後你不是吧,這是這意味着:

1111 1111 1111 1111 0000 0000 0000 0000

最高位是簽名位(無論是正還是負),因此它給出了一個負數。

2

這是做位補,此輸出可以幫助您瞭解正在發生的事情更好:

std::cout << std::hex << " b: " << std::setfill('0') << std::setw(8) << b 
      << " ~b: " << (~b) << " -65536: " << -65536 << std::endl ; 

,我得到如下結果:

b: 0000ffff ~b: ffff0000 -65536: ffff0000 

所以我們設置低16位1這讓我們0000ffff,然後我們做一個補充,將低16位0高端16位設置爲1這讓我們ffff0000等於牛逼-65536十進制。

在這種情況下,因爲我們與位運算的工作,檢查十六進制數據爲我們提供了一些見解,到底是怎麼回事。

9

假設32位整數

int b = 0xFFFF; => b = 0x0000FFFF 
~b = 0xFFFF0000 

頂部位現在設置。假設2s complement,這意味着我們有一個負數。反轉其他位,然後加1給出0x0001000065536

1

結果取決於您的平臺上簽名整數的表示方式。最常見的表示法是使用「二進制補碼」算法表示負值的32位值。也就是說,負值-x由與無符號值2^32 - x相同的位模式表示。

在這種情況下,原始位模式具有低16位設置:

0x0000ffff 

的按位求反清除這些位,並設置高16位:

0xffff0000 

解釋此作爲負數給出值-65536

通常情況下,當您在逐位算術中進行混亂時,您會希望使用無符號類型,以避免這種混淆。

0

您的評論:

如果是 'B' 不..然後輸出應爲0,但爲什麼-65536

建議你期待的結果:

uint32_t x = 0xFFFF; 
uint32_t y = ~x; 

0

這將是一個邏輯不是真正的操作,如:

uint32_t x = 0xFFFF; 
uint32_t y = !x; 

...但operator~不是邏輯沒有,但一個按位沒有。有一個很大的不同。

邏輯返回0表示非0值(對於真值爲false),對於0值則返回1。

但是按位並不反轉給定值中的每一位。因此,0xF的二進制NOT:

0x0F: 00000000 11111111 
~0x0F: 11111111 00000000 

不是零,而是0xF0。