一段代碼的疑問(1)——unsigned與signed,unsignedsigned

來源:互聯網
上載者:User

一段代碼的疑問(1)——unsigned與signed,unsignedsigned
現象:

先來看一段代碼:


這段代碼的輸出結果是:

-84

4294967264

分析:
xiaoqiang@dev:~/cpp$ g++ -g c212.cc -o tempxiaoqiang@dev:~/cpp$ lsc143.cc  c144.cc  c212.cc  temp
可以看到多出一個temp檔案
xiaoqiang@dev:~/cpp$ gdb tempGNU gdb (Ubuntu/Linaro 7.4-2012.04-0ubuntu2.1) 7.4-2012.04Copyright (C) 2012 Free Software Foundation, Inc.License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>This is free software: you are free to change and redistribute it.There is NO WARRANTY, to the extent permitted by law.  Type "show copying"and "show warranty" for details.This GDB was configured as "x86_64-linux-gnu".For bug reporting instructions, please see:<http://bugs.launchpad.net/gdb-linaro/>...Reading symbols from /home/xiaoqiang/cpp/temp...done.(gdb) list1       #include <iostream>2
(gdb) b 6Breakpoint 1 at 0x4007ea: file c212.cc, line 6.

3 int main(){4 unsigned u = 10;5 int i = -42;6 std::cout << i + i << std::endl;7 std::cout << u + i << std::endl;8 return 0;9 }(gdb)
進入到gdb偵錯模式我們來看個究竟
(gdb) b 6Breakpoint 1 at 0x4007ea: file c212.cc, line 6.
開始運行,就會發現程式停在了第6行
(gdb) rStarting program: /home/xiaoqiang/cpp/temp warning: no loadable sections found in added symbol-file system-supplied DSO at 0x7ffff7ffa000Breakpoint 1, main () at c212.cc:66               std::cout << i + i << std::endl;(gdb) 
我們來看看i的二進位值是多少
(gdb) print /t i$1 = 11111111111111111111111111010110
在使用unsigned int 和 int類型變數運算的時候,首先會將int類型轉換成(看成)unsigned int類型,上面兩個值在記憶體中相加為:11111111  11111111  11111111  01100000十六進位為 FFFFFFE0十進位為4294967264練習:看一下下面代碼猜一下最終輸出結果:
xiaoqiang@dev:~/cpp$ gdb tempGNU gdb (Ubuntu/Linaro 7.4-2012.04-0ubuntu2.1) 7.4-2012.04Copyright (C) 2012 Free Software Foundation, Inc.License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>This is free software: you are free to change and redistribute it.There is NO WARRANTY, to the extent permitted by law.  Type "show copying"and "show warranty" for details.This GDB was configured as "x86_64-linux-gnu".For bug reporting instructions, please see:<http://bugs.launchpad.net/gdb-linaro/>...Reading symbols from /home/xiaoqiang/cpp/temp...done.(gdb) list1       #include <iostream>23       int main(){4               unsigned u1 = 42, u2 = 10;5               std::cout << u1 - u2 << std::endl;6               std::cout << u2 - u1 << std::endl;7               return 0;8       }(gdb)
看一下u1和u2的二進位表示
Breakpoint 1, main () at c213.cc:55               std::cout << u1 - u2 << std::endl;(gdb) next326               std::cout << u2 - u1 << std::endl;(gdb) next42949672647               return 0;(gdb) print /t u2$2 = 1010(gdb) print /t u1$3 = 101010(gdb) 
差值為11111111  111111111  11111111  11100000如果以unsigned int 類型顯示則是 4294967264,如果以int類型顯示(有符號)則為-32.相關知識:1、什麼是GDBGDB是GNU開源組織發布的一個強大的UNIX下的程式調試工具。或許,各位比較喜歡那種圖形介面方式的,像VC、BCB等IDE的調試,但如果你是在 UNIX平台下做軟體,你會發現GDB這個調試工具有比VC、BCB的圖形化調試器更強大的功能。所謂“寸有所長,尺有所短”就是這個道理。
2、GDB的基本命令編譯時間必須加上參數-g ,例:g++ -g temp.cpp -o temp.通過Gcc編譯產生可執行檔才能用Gdb進行調試。進入gdb介面:gdb temp. 提示符變成(gdb)(1)查看檔案在Gdb中鍵入”l”(list)就可以查看所載入的檔案(2)設定斷點只需在”b”後加入對應的行號即可(這是最常用的方式,另外還有其他方式設定斷點)。如下所示:(gdb)b 6代碼運行到第五行之前暫停(並沒有運行第五行)。(3)查看斷點情況(Gdb) info b(4)運行代碼Gdb預設從首行開始運行代碼,可鍵入”r”(run)即可(若想從程式中指定行開始運行,可在r後面加上行號)。(5)查看變數值查看斷點處的相關變數值。在Gdb中只需鍵入”p”+變數值即可,如下所示:(Gdb) p nGdb在顯示變數值時都會在對應值之前加上”$N”標記,它是當前變數值的引用標記,所以以後若想再次引用此變數就可以直接寫作”$N”,而無需寫冗長的變數名。
(6)單步運行
使用命令”n”(next)或”s”(step),它們之間的區別在於:若有函數調用的時候,”s”會進入該函數而”n”不會進入該函數。因此,”s”就類似於VC等工具中的”step in”,”n”類似與VC等工具中的”step over”。(7)恢複程式運行使用命令”c”(continue).在Gdb中,程式的運行狀態有“運行”、“暫停”和“停止”三種,其中“暫停”狀態為程式遇到了斷點或觀察點之類的,程式暫時停止運行,而此時函數的地址、函數參數、函數內的局部變數都會被壓入“棧”(Stack)中。故在這種狀態下可以查看函數的變數值等各種屬性。但在函數處於“停止”狀態之後,“棧”就會自動撤銷,它也就無法查看各種資訊了。
(8)查看資料print  variable        查看變數print  *array@len      查看數組(array是數組指標,len是需要資料長度)可以通過添加參數來設定輸出格式:/x 按十六進位格式顯示變數。 /d 按十進位格式顯示變數。
/u 按十六進位格式顯示無符號整型。
/o 按八進位格式顯示變數。
/t 按二進位格式顯示變數。 
/a 按十六進位格式顯示變數。
/c 按字元格式設定顯示變數。
/f 按浮點數格式顯示變數。







C語言中unsigned與signed資料的轉換

先講一下 原碼 補碼 反碼的 概念
正整數的 原碼 補碼 反碼 都是一樣的

負數的反碼是將其原碼除 符號位之外的各位取反
負數的補碼是將其原碼除 符號位之外的各位取反 再在末尾加1

假設 存在 一個位元組的整型 signed int8 x = -5
x的原碼1000 0101(最高位是符號位 1表示負 0表示正)
x的反碼1111 1010
x的補碼1111 1011

儲存的計算中的 -5 不是我們更能理解的10000101,而是 -5 的補碼1111 1011

現在 回答你的問題:
unsigned int e,f=12345;
f是無符號 所以 f的 原碼 補碼是一樣的:0000 0100 1101 0011
因此c還是等於12345

signed int c,d=-15;
d是負數 所以 d的原碼是1000 0000 0000 1111
d的補碼是1111 1111 1111 0001

c = f = 0000 0100 1101 0011 轉換成 十進位 就是 12345
e = d = 1111 1111 1111 0001 因為e是無符號整型 所以電腦直接將
1111 1111 1111 0001 當做正整數來處理的,沒有了補碼轉換成原碼的過程了。
因此你看到的e不是等於 -15 (用十進位表示)而是 65521(用十進位表示)

總結:這個問題的關鍵是 我們在電腦螢幕上看到的是 原碼;而儲存的計算中的是 補碼。正整數的原碼 補碼是一樣的,而負數的原碼 補碼是 不一樣的,
如果你瞭解這個概念的話,這個問題就很容易理解了
 
C語言中unsigned與signed在聲明時有什作用

主要是取值範圍。

unsigned和signed在一種類型下,unsigned表示在這個範圍大小的整數,signed一般都是在這個範圍內的從負到正

有什麼不明白可以HI我 細聊
 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.