日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

代码里-3gt;gt;1是-2但3gt;gt;1是1,-3/2却又是-1,为什么?

發(fā)布時間:2023/12/20 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 代码里-3gt;gt;1是-2但3gt;gt;1是1,-3/2却又是-1,为什么? 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

之前群里有個同學(xué)向大家提出了類似這樣的問題。隨后這位同學(xué)公布了答案:右移運算是向下取整,除法是向零取整。這句話對以上現(xiàn)象做了很好的總結(jié),可是本質(zhì)原因是什么呢?

我一直以為-3>>1的結(jié)果是-1。所以打算思考一下這個問題。

補碼

首先我們看看-3存儲的形態(tài)是怎么樣的:

int?main() {int?n?=?-3;printf("0x%x",n); }

打印結(jié)果為:

0xfffffffd

這是32位有符號數(shù)負(fù)數(shù)的補碼形式,即0x3按位取反之后0xfffffffc再加一,即為0xfffffffd

為什么會有這樣的“奇怪”的補碼形式呢?首先一個32位的寄存器的值的范圍是0~0xffffffff (8個f)。如果僅僅表示正數(shù)的話,即無符號整型數(shù),所有的值都是正數(shù)的情況下范圍是0~4294967295(0xffffffff)

那么如果我想表示負(fù)數(shù)呢???比如我想在計算機中表達-1這個數(shù)字,正1很簡單就0x1嘛。那么根據(jù)1和-1相加等于0以及整型相加溢出的bit會被丟棄的特性,-1就可以是0xffffffff

例如:0xffffffff + 0x1 = 0x100000000(32bit計算機中此處最高位的1會被丟棄) = 0x00000000

0x1怎么轉(zhuǎn)化成0xffffffff,就是按位取反(0xfffffffe)后再加一嘛,這個就是補碼的說法了。

然后呢,正負(fù)兩種數(shù)的范圍就對半分吧。正數(shù):0 ~ 0x7fffffff,負(fù)數(shù):0x80000000 ~ 0xffffffff

0x80000000 是很特殊的數(shù),和0一樣,0x80000000只有和自己相加才會等于“零”。如果把0x80000000 歸類成負(fù)數(shù)的話,那么就有一個明顯的規(guī)律了,那就是最高位的bit為1的數(shù)都是負(fù)數(shù),最高位bit為0的數(shù)都是正數(shù)。

這就是最高位是符號位的規(guī)定。

整型數(shù)字的移位(-3>>1為啥等于-2)

這里我們想確鑿地弄清楚這個過程,只能借助匯編代碼了。方法即為:

  • 準(zhǔn)備好一段C代碼

  • 編譯這段代碼

  • 反匯編可執(zhí)行文件,查看匯編代碼

  • 因為我更擅長一點arm的匯編代碼,所以需要在 https://www.linaro.org/downloads/上下載arm的交叉編譯工具鏈,這個比較方便,因為不需要編譯,直接下載后就可以在Linux環(huán)境上執(zhí)行了。

    準(zhǔn)備以下代碼:

    #include<stdio.h> int?shift(int?a,?int?b) {return?(a?>>?b); }unsigned?int?shift_u(unsigned?int?a,?unsigned?int?b) {return?(a?>>?b); }main(){int?a?=?shift(-3,?1);unsigned?int?b?=?shift_u(3,?1);printf("[%d][%u]",a,b); }

    下載好linaro的gcc和glibc之后執(zhí)行:

    ~/linro/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc?test.c?--sysroot=~/linro/sysroot-glibc-linaro-2.25-2019.12-arm-linux-gnueabihf/

    然后反匯編:

    ~/linro/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-objdump?-d?a.out

    可以看到有符號的移位操作:

    asr.w???r3,?r2,?r3

    無符號數(shù)的移位操作:

    lsr.w???r3,?r2,?r3

    以上指令的意思是將r2的值右移r3次,并將結(jié)果賦值到r3中。

    關(guān)于asr和lsr可以在官方文檔中找到解釋:https://developer.arm.com/documentation/dui0497/a/the-cortex-m0-instruction-set/about-the-instruction-descriptions/shift-operations

    Arithmetic shift right by n bits moves the left-hand 32-n bits of the register Rm, to the right by n places, into the right-hand 32-n bits of the result, and it copies the original bit[31] of the register into the left-hand n bits of the result

    asr和lsr不同之處在于,asr指令會在移位之后,將原來的最高位bit[31]重新賦值到結(jié)果里。

    所以-3 >> 1的過程應(yīng)該是這樣的:

    0xfffffffd右移一位是0x7ffffffe,然后再置位最高位符號位,結(jié)果為:0xfffffffe,這就是-2的補碼表現(xiàn)形式。

    整型數(shù)字的除法(-3/2為啥等于-1)

    那么為啥-3/2等于-1,難道在做除法的時候不會用移位進行優(yōu)化嗎?

    多說無益,只能按照套路來反匯編,還是一樣的套路代碼。

    #include<stdio.h>int?div(int?a,?int?b) {return?(a?/?b); }unsigned?int?div_u(unsigned?int?a,?unsigned?int?b) {return?(a?/?b); }main(){int?a?=?div(-3,?2);unsigned?int?b?=?div_u(3,?2);printf("[%d][%d]",a,b); }

    如果使用linaro上的armv8的交叉編譯工具鏈,那么可以看到div函數(shù)調(diào)用的指令是:

    sdiv????r3,?r2,?r3,

    div_u函數(shù)調(diào)用的指令是:

    udiv????r3,?r2,?r3

    顯然除法對于有符號數(shù)和無符號數(shù)做了區(qū)分,但是我們無法看到內(nèi)部的區(qū)別,所以要用armv7的編譯鏈反匯編,因為armv7沒有直接的div指令,所以我們可以看到匯編中除法都做了什么。

    此處我們主要看有符號數(shù)除法和無符號數(shù)除法的區(qū)別,而匯編篇幅太長,在此我只截取有符號數(shù)除法中有,而無符號數(shù)除法不存在也不需要的那部分代碼,這樣就能看到-3/2和3/2的區(qū)別。有符號數(shù)除法一開始的處理:

    //此處被除數(shù)是r0,除數(shù)是r1 <__divsi3>: cmp?????r1,?#0?//判斷r1和0的關(guān)系,并更新cpsr寄存器 beq.w???1098a?<.divsi3_skip_div0_test+0x27c>?//如果除數(shù)等于0,那么跳轉(zhuǎn)<.divsi3_skip_div0_test>: eor.w ? ip, r0, r1 //將除數(shù)和被除數(shù)進行異或并將結(jié)果存儲到ip寄存器中,但是不會更新cpsr寄存器 it??????mi?//判斷cpsr中的Negative?Flag negmi???r1,?r1?//如果r1為負(fù)數(shù)則改成正數(shù) subs????r2,?r1,?#1 beq.w???1095a?<.divsi3_skip_div0_test+0x24c>?//如果r1為1則跳轉(zhuǎn) movs????r3,?r0 it??????mi negmi???r3,?r0?//如果r0為負(fù)數(shù)則改成正數(shù) //接下來就進行和無符號數(shù)一樣的常規(guī)除法算法

    以及有符號數(shù)除法對結(jié)果的處理:

    cmp.w???ip,?#0? it ???? mi //如果異或結(jié)果為負(fù),則表示被除數(shù)和除數(shù)的符號不相同,那么結(jié)果必然是負(fù)數(shù) negmi???r0,?r0?//如果異或結(jié)果為負(fù),把結(jié)果賦成負(fù)值 bx??????lr?//返回到函數(shù)調(diào)用處的后一個指令

    以上可以看到對有符號數(shù)的除法處理會這樣:

  • 記錄除數(shù)和被除數(shù)的符號是否相同

  • 將被除數(shù)和除數(shù)都轉(zhuǎn)成正數(shù)

  • 除法算法結(jié)束之后,根據(jù)第一步的結(jié)果,來決定是不是把結(jié)果賦值成負(fù)數(shù)。

  • 所以-3/2的時候,會先計算3/2,得到1之后再賦值成-1

    還記得那個神奇的數(shù)字0x80000000(-2147483648)嗎,0x80000000乘以-1依然是0x80000000如果是這個數(shù)字除以2會是什么結(jié)果呢。

    0x80000000/2的步驟如下:

  • 記錄兩個數(shù)字異或結(jié)果,如果兩個數(shù)字的符號位不同,說明結(jié)果為負(fù),反之為正

  • 對0x80000000進行乘以-1處理,結(jié)果依然還是0x80000000

  • 將0x80000000當(dāng)作是無符號數(shù)進行除以2操作得到:0x40000000

  • 把0x40000000賦值為負(fù)數(shù)即為0xC0000000 (-1073741824)

  • 以上就是arm中對于有符號數(shù)的移位和除法操作。如果你對匯編中的除法算法的具體步驟有興趣的話,點個贊,下一篇arm除法匯編實現(xiàn)全面解析!Binfun已經(jīng)把arm的匯編除法轉(zhuǎn)譯成C,并從中學(xué)習(xí)到了很多,敬請關(guān)注!

    推薦閱讀:

    專輯|Linux文章匯總

    專輯|程序人生

    專輯|C語言

    我的知識小密圈

    總結(jié)

    以上是生活随笔為你收集整理的代码里-3gt;gt;1是-2但3gt;gt;1是1,-3/2却又是-1,为什么?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 欧美日韩一二三四 | 天堂久久精品 | 亚洲国产av一区二区三区 | 国产第1页| 成人依人 | 天天拍夜夜拍 | 亚洲一区二区三区欧美 | 欧美黄色图片 | 性生交大片免费看视频 | 精品国产高清在线观看 | 成人免费视频一区 | 隔壁邻居是巨爆乳寡妇 | 中文字幕 日韩 欧美 | 亚洲精品在线不卡 | 永久久久久久 | 免费视频毛片 | 色婷婷在线播放 | 99re色 | 天天躁狠狠躁 | 老司机伊人 | 黑人巨大猛烈捣出白浆 | 国产在线一二区 | 亚洲一级Av无码毛片久久精品 | 激情 小说 亚洲 图片 伦 | 日本草草影院 | 性涩av | 67194少妇在线观看 | 欧美成人h版在线观看 | 草草在线免费视频 | 精品国产一区二 | 日日夜夜精品视频免费 | 国产性猛交96 | 告诉我真相俄剧在线观看 | 天堂а√在线最新版中文在线 | 糖心av | 男人av在线 | 捆绑裸体绳奴bdsm亚洲 | 99久久国产宗和精品1上映 | 一二区视频 | 国产尻逼| 在线观看深夜视频 | 免费观看在线播放 | 91福利视频导航 | 91播放在线 | 毛片基地在线观看 | 日本bdsm视频 | 岛国精品一区 | 欧美成人三级在线观看 | 抱着老师的嫩臀猛然挺进视频 | 在线视频激情小说 | 欧美黑人欧美精品刺激 | 懂色av一区二区三区蜜臀 | 美女被娇喘流出白 | 国产精品美女www | 黄色靠逼视频 | 欧美天堂 | 久艹在线播放 | 奇米色婷婷| 日本道中文字幕 | 麻豆自拍视频 | 日韩一级片在线观看 | 久久五十路 | 美国毛片av | 男女草比视频 | 东北少妇不带套对白 | 日韩精品视频在线播放 | 欧美一区二区三区在线观看视频 | 免费毛片看 | 九九热视频这里只有精品 | 一级片成人 | 国产美女操 | 亚洲一区在线免费 | 亚洲中文字幕在线观看 | 亚洲夜夜操 | 中文黄色片 | 韩国伦理中文字幕 | 国产一区二区精华 | 伊人影视大全 | 天堂中文在线8 | 在线播放视频高清在线观看 | 在线免费观看成人 | 久久久久久久久久av | 黑人vs亚洲人在线播放 | 欧美性生活在线视频 | www,超碰 | 成人在线小视频 | 久久男| 欧美一区二区三区久久 | 青青草在线免费观看 | www在线播放 | 日韩在线视频网址 | 欧美日韩一区二区三区视频 | 精品无人区无码乱码毛片国产 | 中文字幕视频免费观看 | 国产精品国产精品国产专区蜜臀ah | 超碰cc | 爱看av在线| 三级黄色片免费观看 | 男女交性视频 |