什么瀏覽器可以進(jìn)黃頁zol問答沈陽seo按天計(jì)費(fèi)
目錄
一、位操作符
1.位與&
2.位或|
3.位取反~
4.位異或^
5.位與,位或,位異或的特點(diǎn)總結(jié)
6.左移位《《? 右移位? ?》》
二、位與,位或,位異或在操作寄存器時(shí)的特殊作用
1.寄存器操作的要求(特定位改變而不影響其他位)
2.特定位清零用&
3.特定位置1用|
4.特定位取反用^
三、用位運(yùn)算構(gòu)建特定二進(jìn)制數(shù)
1.寄存器位操作經(jīng)常需要特定位給特定值
2.使用位移獲取特定位為1的二進(jìn)制數(shù)
3.再結(jié)合位取反獲取特定位為0的二進(jìn)制數(shù)
4.總結(jié):
四、位運(yùn)算實(shí)戰(zhàn)
1.例題1
2.例題2
3.例題3
4.例題4
5.例題5
6.例題6
7.例題7
8.例題8
方法1:
方法2:
五、用宏定義完成位運(yùn)算
1.直接用宏來置位【賦1】,復(fù)位【賦0】(最右邊為第1位)
1.1
1.2
1.3
2.截取遍歷的部分連續(xù)位
一、位操作符
1.位與&
(1)位與符號(hào)是一個(gè)&,兩個(gè)&&是邏輯與
(2)真值表:1&0=0? ?1&1=1? ?0&0=0? ? 0&1=0
(3)從真值表可以看出:位與操作的特點(diǎn)是,只有1和1位于結(jié)果為1,其余全是0
(4)位于和邏輯與的區(qū)別:位與時(shí)兩個(gè)操作數(shù)是按照二進(jìn)制位批次對應(yīng)位相與的,
????????邏輯與是兩個(gè)操作數(shù)作為整體來相與的(舉例:0xAA&0xF0=0xA0? ? ,0xAA && 0xF0=1)
2.位或|
(1)位或符號(hào)是一個(gè)|,兩個(gè)||是邏輯或
(2)真值表;1|0=1 1|1=1 0|0=0 0|1=1
(3)從真值表可以看出:位或時(shí)兩個(gè)操作數(shù)是按照二進(jìn)制彼此對應(yīng)位相與的,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?邏輯或是兩個(gè)操作數(shù)作為整體來相或的。
3.位取反~
(1)C語言中位取反是~,C語言中的邏輯取反是!
(2)按位取反是將操作數(shù)的二進(jìn)制位逐個(gè)按位取反(1變成0,0變成1)
? ? ? ? 邏輯取反是真(在C語言中只要不是0的任何數(shù)都是真)變成假(在C語言中只有0表示假),假變成真。
#include<stdio.h>
int main() {int a = 45;int b, c;b = ~a; //按位取反,逐個(gè)位操作,1變0,0變1c = !a; //按邏輯取反【整體改變】,真變假,假變真printf("b=%d\n", b);//-64printf("c=%d\n", c);//0}
#include<stdio.h>
int main() {int a = 45;int b, c;b = ~(~a); //等價(jià)于~~ac = !(!a); //等價(jià)于!!aprintf("b=%d\n", b);//45printf("c=%d\n", c);//1}
實(shí)驗(yàn);
? ? ? ? 任何非0的數(shù)被按邏輯取反再取反就會(huì)得到1
? ? ? ? 任何非0的數(shù)被按位取反再取反就會(huì)得到它自己
4.位異或^
(1)異或真值表:1^1=0? 0^0=0? 1^0=1? 0^1=1(記憶方法:2個(gè)數(shù)如果相等結(jié)果為0,不等結(jié)果為1)
//45:0010 1101//^//23:0001 0111//= 0011 1010=58unsigned int a = 45, b = 23;unsigned int c;c = a ^ b;//58printf("c=%d\n", c);
5.位與,位或,位異或的特點(diǎn)總結(jié)
位與:(任何數(shù),其實(shí)就是1和0)與1位與無變化,與0位于變成0
位或:(任何數(shù),其實(shí)就是1和0)與1位或變成1,與0位或無變化
位異或:(任何數(shù),其實(shí)就是1和0)與1位異或會(huì)取反,與0位異或無變化
6.左移位《《? 右移位? ?》》
C語言的位移要取決于數(shù)據(jù)類型
對于無符號(hào)數(shù),左移動(dòng)時(shí)右側(cè)補(bǔ)0(相當(dāng)于邏輯移位)
對于無符號(hào)數(shù),右移動(dòng)左側(cè)補(bǔ)0(相當(dāng)于邏輯移位)
對于有符號(hào)數(shù)。左移時(shí)候右側(cè)補(bǔ)0(角算術(shù)移位,相當(dāng)于邏輯移位)
對于有符號(hào)數(shù),右移動(dòng)時(shí)候左側(cè)補(bǔ)符號(hào)位(如果整數(shù)就0,負(fù)數(shù)就補(bǔ)1,叫算術(shù)移位)
二、位與,位或,位異或在操作寄存器時(shí)的特殊作用
1.寄存器操作的要求(特定位改變而不影響其他位)
(1)ARM是內(nèi)存與IO統(tǒng)一編址的,ARM中有很多內(nèi)部外設(shè),SoC中的CPU通過向這些內(nèi)部外設(shè)的寄存器寫入一些特定的值來操控逐個(gè)內(nèi)部外設(shè),進(jìn)而操控硬件動(dòng)作。所以可以說,讀寫寄存器就是操控硬件
(2)寄存器的特定是按位進(jìn)行規(guī)劃和使用。但是寄存器的讀寫卻是整體32位一起進(jìn)行的。(也就是說你只想修改
(3)寄存器操作要求是:在設(shè)定特定位時(shí)不能影響其他位。
(4)如何做到?答案是:讀-改-寫(三部曲)。讀改寫的操作理念,就是:當(dāng)我想改變一個(gè)寄存器中某些特定位時(shí),我不會(huì)直接去給他寫,我會(huì)先讀出寄存器整體原來的值,然后再逐個(gè)基礎(chǔ)上修改我想要修改的特定位,再將修改后的值整體寫入寄存器。這樣達(dá)到的效果是:再不影響其他位原來值的情況下,我關(guān)心的位的值硬件被修改了。
2.特定位清零用&
位與:(任何數(shù),其實(shí)就是1和0)與1位與無變化,與0位于變成0
(2)如果希望將一個(gè)寄存器的某些特定位變成0而不影響其他位,可以構(gòu)造一個(gè)合適的1和0組成的數(shù)和這個(gè)寄存器原來的值進(jìn)行位與操作,就可以將特定位清零
(3)假設(shè)原來32位寄存器中的值為:0xaaaa aaaa,我們希望將bit8-bit15清零而其他位不變,可以將這個(gè)數(shù)與0xffff 00ff進(jìn)行位與即可【想要變成0的位直接寫上0,其他位寫1即可】
#include<stdio.h>
int main() {unsigned int a = 0xaaaaaaaa;unsigned int b = 0xffffffff;unsigned int c;//將想要變成0的位置寫上0,其他位寫上1c = a & b;printf("c=0x%x\n", c);//0xaaaaaaaa
}
3.特定位置1用|
位或:(任何數(shù),其實(shí)就是1和0)與1位或變成1,與0位或無變化
(2)要置1的位寫上1,其他位為0,然后將這個(gè)數(shù)與相關(guān)的數(shù)進(jìn)行位或
//位或:特定位置1用|//把寄存器值的bit4-bit7置1,其他位不變unsigned int a = 0x123d0c57;unsigned int b = 0xf0;unsigned int c;c = a | b;printf("c=0x%x\n", c);//0x123d0cf7
4.特定位取反用^
位異或:(任何數(shù),其實(shí)就是1和0)與1位異或會(huì)取反,與0位異或無變化
(2)要取反的特定位為1,其他位取0,然后將這個(gè)數(shù)與原來的數(shù)進(jìn)行位異或即可。
//異或:特定位取反用^//把寄存器值的bit4-bit7取反,其他位不變unsigned int a = 0x123d0cd7;unsigned int b = 0xf0;unsigned int c;c = a ^ b;printf("c=0x%x\n", c);//0x123d0c27
三、用位運(yùn)算構(gòu)建特定二進(jìn)制數(shù)
1.寄存器位操作經(jīng)常需要特定位給特定值
(1)由上節(jié)課可以找到:對寄存器特定位進(jìn)行置1或者清0或者取反,關(guān)鍵性的難點(diǎn)在于要事先構(gòu)建一個(gè)特定的數(shù),這個(gè)數(shù)和原來的值進(jìn)行位與,位或,位異或等操作,既可達(dá)到我們對寄存器操作的要求。
(2)解法1:用工具,難度也不大,操作起來也不是太麻煩
? ? ? ? 解法2:自己寫代碼用位操作符號(hào)(主要是移位和位取反)來構(gòu)建這個(gè)特定的二進(jìn)制數(shù)
2.使用位移獲取特定位為1的二進(jìn)制數(shù)
(1)最簡單的是用移位來獲取一個(gè)特定位為1的二進(jìn)制數(shù)。比如我們需要一個(gè)bit3-bit7為1(隱含意思是其他位全部為0)的二進(jìn)制數(shù),可以
? ? ? ? 1)先寫出5位為1的數(shù)(0x1f==>bit0-bit4)
? ? ? ? 2)然后將這個(gè)數(shù)左移3位(0x1f<<3==》bit3-bit7)
(2)更難一點(diǎn)的:獲取bit3-bit7為1,同時(shí)bit23-bit25為1,其他位為0
? ? ? ? ((0x1f<<3) | (0x7<<23))
#include<stdio.h>
int main() {//下面表達(dá)式的含義:位或說明這個(gè)數(shù)字由2部分組成,第一部分中左移2位說明第一部分從bit3開始//第一部分?jǐn)?shù)字位0x1f說明這部分有5位,所以第一部分其實(shí)是bit3到bit7//第二部分的解讀方法同樣的,可知第二部其實(shí)是bit23到bit25unsigned int a;a = ((0x1f << 3) | (0x7 << 23));printf("a=0x%x\n", a);//a=0x38000f8return 0;
}
3.再結(jié)合位取反獲取特定位為0的二進(jìn)制數(shù)
(1)現(xiàn)在我們要獲取bit4-bit10為0,其余位全部為1的數(shù)。怎么做?
(2)利用上面講的方法就可以:(0xf<<0) | (0x1fffff<<11)
unsigned int a;a = ((0xf << 0) | (0x1fffff << 11));printf("a=0x%x\n", a);//a=0xfffff80freturn 0;
(3)但是這些存在問題:連續(xù)為1的位數(shù)太多了,這個(gè)數(shù)字本身就很難構(gòu)造,所以這種方法的優(yōu)勢損失了
(4)思路是:先試圖構(gòu)造出這個(gè)數(shù)的位相反數(shù),再取反得到這個(gè)數(shù)。(比如本例中要構(gòu)造的數(shù)bit4-bit10為0,其他位為1),那我們先構(gòu)造出一個(gè)bit4-bit10為1,其他位為0的數(shù),然后對這個(gè)數(shù)按位取反即可。
//使用位移+取反unsigned int a;a = ~(0x7f<<4);printf("a=0x%x\n", a);//a=0xfffff80freturn 0;
4.總結(jié):
(1)如果你要的這個(gè)數(shù)比較少位為1,大部分位為0,則可以通過連續(xù)很多個(gè)1左移n位得到
(2)如果你想要的這個(gè)數(shù)是比較少位為0,大部分為1,則可以通過先根據(jù)其位反數(shù),然后再位取反來得到
(3)如果你想要得到的數(shù)中連續(xù)1(連續(xù)0)的部分不止1個(gè),那么可以通過多段分別構(gòu)建,然后再彼此位與【|】即可。這個(gè)時(shí)候因?yàn)閰⑴c位或運(yùn)算的各個(gè)數(shù)為1的位是不重復(fù)的,所以這時(shí)候的位或其實(shí)相當(dāng)于幾個(gè)數(shù)的疊加。
四、位運(yùn)算實(shí)戰(zhàn)
要置1用|,用清零用&,要取反用^,~和《《 》》用來構(gòu)建特定二進(jìn)制數(shù)。
1.例題1
給定一個(gè)整形數(shù)a,設(shè)置a的bit3,保證其他位不變。
a=a|(1<<3) 或者 a|=(1<<3)
2.例題2
給定一個(gè)整形數(shù)a,設(shè)置a的bit3-bit7,保證其他位不變。
a=a|(0x1f<<3) 或者 a|=0x1f
3.例題3
給定一個(gè)整形數(shù)a,清除a的bit15,保證其他位不變。
a=a& ~(0x1<<15) 或者 a&=~(0x1<<15)
4.例題4
給定一個(gè)整形數(shù)a,清除a的bit15-bit23,保證其他位不變。
a=a&(~(0x1ff<<15)) 或者 a&=(~(0x1ff<<15))
5.例題5
給定一個(gè)整形數(shù)a,取出a的bit3-bit8
思路:
? ? ? ? 第一步:先講這個(gè)數(shù)bit3-bit8不變,其他位全部清零--->a=a&(0x3f<<3)
? ? ? ?第二步:再講其右移3位得到結(jié)果
//第一步:把bit3到bit8的位保持不變,其余位全部清零
a=a& (0x3f<<3)
//第二步:將其右移3位
a>>=3;
6.例題6
將一個(gè)寄存器的bit7-bit17中的值賦值937(其余位不受到影響)
關(guān)鍵點(diǎn):不能影響其他位,并不知道原來bit7-bit17中裝的值
思路
? ? ? ? 第一步:先將bit7-bit18全部清零,當(dāng)然不能影響其他位
? ? ? ? 第二部:將bit7-bit17進(jìn)行賦值【使用”|“因?yàn)槲覀円x值】
//第一步:bit7-bit17全部清零
a&=~(0x7ff<<7);
//第二步:bit7-bit17賦值937
a|=(937<<7);
7.例題7
將一個(gè)寄存器的bit7-bit17中的值+17(其余位不受到影響)
關(guān)鍵點(diǎn):不知道原來的值是多少,
? ? ? ?思路:
? ? ? ? ? ? ? ? 第一步:先讀出原來的bit7-bit17的值
? ? ? ? ? ? ? ? 第二步:給這個(gè)值加17
? ? ? ? ? ? ? ? 第三步:將bit7-bit17清零
? ? ? ? ? ? ? ? 第四步:將第二步算出來的值寫入bit7-bit17
unsigned int a=0xc30288f8;//第一步:先讀出原來的bit7-bit17的值unsigned int tmp;tmp=a&(0x3ff<<7);//使用【&】和全1將這10位數(shù)進(jìn)行計(jì)算tmp=tmp>>7//將其移動(dòng)到低位取出//第二步:給這個(gè)值加17tmp+=17;//第三步:將bit7-bit17清零a=a & ~(0x3f<<7);//第四步:將第二步算出來的值寫入bit7-bit17a=a| (tmp<<7);
8.例題8
將一個(gè)寄存器的bit7-bit17中的值賦值937(其余位不受到影響),同時(shí)個(gè)bit21-bit25賦值17
方法1:
unsigned int a;
unsigned int tmp;
//第一步:先將bit7-bit17位全部置為0
a=a&~(0x7ff<<7);
//第二步:將這幾位進(jìn)行賦值
a=a|(937<<7);
//第三步:先取出bit21-bit25
tmp=a&(0x1f<<21);
tmp=tmp>>21;
//第四步:將17加上
tmp+=17;
//第五步:將bit21-bit25置為0
a=a&~(0x1f<<21);
//第六步;將tmp放回到bit21-bit25
a=a|(tmp<<21);
方法2:
unsigned int a=0x30288f8;
a&=~((0x3ff<<7) | (0x1f<<21));//bit7-bit17和bit21-bit25全部清零
a|=((937<<7) | (17<<21));//937和17全部賦值
五、用宏定義完成位運(yùn)算
1.直接用宏來置位【賦1】,復(fù)位【賦0】(最右邊為第1位)
1.1
用宏定義將32位數(shù)的第n位(右邊其算,也就是bit0是第二位)置位【變成1】
//第一題:用宏定義將32位數(shù)的第n位(右邊其算,也就是bit0是第二位)置位【變成1】
//1U:表示無符號(hào)1---》(x | (1U <<(n-1)))
#define SET_BIT_N(x,n) (x | (1<<(n-1)))//因?yàn)槲覀兪菑腷it0開始算的
int main() {unsigned int a = 0;unsigned int b = 0;b=SET_BIT_N(a, 4);//對應(yīng)bit3printf("0x%x", b);}
1.2
第二題:用宏定義將32位數(shù)x的第n位(右邊其算,也就是bit0是第1位)清零【變成0】
#include<stdio.h>//第二題:用宏定義將32位數(shù)x的第n位(右邊其算,也就是bit0是第1位)清零【變成0】
#define CLEAR_BIT_N(x,n) (x&~(1U<<(n-1)))
int main() {//第二題unsigned int a = 0xffff;unsigned int b = 0;b= CLEAR_BIT_N(a, 4);//對應(yīng)bit3printf("0x%x", b);//0xfff7}
1.3
用宏定義將32位數(shù)x的第n位到第m位(右邊起算,也就是bit0是第1位)置位【變成1】
我們需要一個(gè)算式得出(m-n+1)個(gè)1
算法:第一步:先得到32位1----》~(0U)
? ? ? ? 第二步:將第一步得到的數(shù)右移x位即可得到(m-n+1)個(gè)1-----》~(0U)>>(32-(m-n+1))
? ? ? ? 第三步:將得出的結(jié)果移回去原來的位置
//第三題:用宏定義將32位數(shù)x的第n位到第m位(右邊起算,也就是bit0是第1位)置位【變成1】
//我們需要一個(gè)算式得出(m-n+1)個(gè)1
//算法:第一步:先得到32位1----》~(0U)
// 第二步:將第一步得到的數(shù)右移x位即可得到(m-n+1)個(gè)1-----》~(0U)>>(32-(m-n+1))
// 第三步:將得出的結(jié)果移回去原來的位置
#define CLEAR_BIT_N_M (x,n,m) (x| (((~0U)>>(32-(m-n+1)))<<(n-1)//第三題unsigned int a = 0x0;unsigned int b = 0;b = CLEAR_BIT_N_M(a,5,8);//對應(yīng)bit3printf("0x%x", b);//
2.截取遍歷的部分連續(xù)位
#define GETBITS(x,n,m) ((x&~(~0U) << (m-n+1)) <<(n-1)) >> (n-1))