【C語言編程入門系列】—— 第八章,C語言基本運算和表達式(四)

? 和二進制極為密切的運算符

  本小節(jié)的運算符需要借助二進制概念來理解。

  二進制數(shù)據(jù)中,比如一個字節(jié)的數(shù)據(jù),它的十進制為228,二進制就為11100100,如圖5.11,

注意:如果不懂怎么轉(zhuǎn)換十進制和二進制,可以借用windows的計算器來輔助。

圖5.11? 228的十進制和二進制表現(xiàn)??

  把 11100100 整體往右邊挪動一位,就會變?yōu)?1110010。如果覺得不好理解?請這么想,有一條火車軌道,軌道只有八節(jié),一列無限長的火車在這八節(jié)軌道上來回移動,如下圖所示:

  火車啟動前,在軌道上對應的車廂上標有一串數(shù)字?11100100,沒有對應的車廂統(tǒng)一設數(shù)字為0,如下圖:

?  當火車往右移動一格的時候,在軌道上車廂顯示的數(shù)據(jù)就為 01110010,當火車往右移動兩格的時候,軌道上車廂顯示的數(shù)據(jù)就為00111001。

   以上就是數(shù)據(jù)右移的表現(xiàn),同理,數(shù)據(jù)左移就好比剛才那列火車向左移動,總之八節(jié)軌道上的車廂只能顯示8個數(shù)字。

   再看看十進制的228,二進制為11100100,右移一位變?yōu)?1110010,十進制值為114,在C語言中有移位運算符 >> 和 << 專門用來讓數(shù)據(jù)移位,如下代碼,

#include void main()

{

? ? unsigned chara =228;

? ? unsigned charb =0;

? ? b = a >>1;

? ? printf("b = %d\n", b);

}

  運行結(jié)果是:b = 114。

注意:C語言printf不能顯示二進制數(shù)據(jù),只能顯示十進制,十六進制和八進制的數(shù)。

  >> 就是右移運算符, << 就是左移運算符。

  小伙伴可以把上述代碼的 >> 改為 << ,向左移動一位就會使得 11100100 變?yōu)?11001000 ,十進制的值就為200。如果移動2位結(jié)果又是怎樣呢,讀者可以自行腦補。

  上述案例用的是 unsigned char 無符號的字符型數(shù)據(jù),它的取值范圍是 0~255,所以不管怎么移動,這個數(shù)據(jù)都是在 0~255 范圍內(nèi)。如果數(shù)據(jù)是unsigned int 類型,那么這列火車的軌道就要加長到32節(jié),數(shù)據(jù)就會在 0~4294967295 之內(nèi)浮動。


  難點來了,如果類型是帶負號的 char 型呢?首先它的范圍只可以在 -128~127 之間,那就隨機選一個數(shù)來研究,比如選124,同樣是剛才那份代碼,將unsigned除去,將 a = 228 改成 a = 124。

  a右移一位運行結(jié)果:b = 62,a 左移一位運行結(jié)果: b = -8 。

? ? ? ?這些都與計算機存儲數(shù)據(jù)方式有關(guān),八個字節(jié)中,第一位是符號位,如果是0表示符號為正,如果是1表示符號為負,因為筆者寫文章動力不足,所以筆者打算不討論這塊,希望讀者自行去了解這塊知識,可以借助windows的計算機結(jié)合寫代碼來分析有符號的數(shù)據(jù)移位規(guī)律是怎樣的。

  下一個講位運算,&,?|? , ^,~

  按位與運算&,看起來很熟悉吧,感覺就是取地址符號一樣,在運算表達式中它的作用是將左邊的數(shù)據(jù)與右邊的數(shù)據(jù)進行與的運算,與運算就是把每個對應的位進行比對,如果都為1這個位就設置為1,如果不相等或者都為0這個位就設置為0,如下圖所示:


  取二進制數(shù) 01011011 同 10011001 進行與運算,結(jié)果為 00011101,與運算規(guī)則正是遵循了同位都為1取1,其它情況取0,代碼如下:

#include void main()

{

? ? unsigned chara =91;

? ? unsigned charb =153;

? ? unsigned charc =0;

? ? c = a & b;

? ? printf("c = %d\n", c);

}

  運行結(jié)果:c = 25,十進制數(shù)25,它的二進制恰好就為圖5.14所運算的結(jié)果為 00011001。


? ? ?同理,按位或運算 | ,就是左邊和右邊兩個數(shù)的每一位進行比對,如果有一個位是1就取1,其它取0。

? ? ? ?異或運算 ^ ,左邊和右邊兩個數(shù)的每一位進行對比,如果相同取0,不同取1。

 ? ? 非運算 ~ ,上面三個運算有左邊的數(shù)和右邊的數(shù),非運算只針對一個數(shù)進行運算,就是將這個數(shù)的每一位都取反,也就是如果是0就取1,如果是1就取0。


   最后講解比較常用的邏輯運算符?&&, ||, !

? ? ?邏輯與 && ,返回的是bool值,也就是返回true或者false,用法如下代碼:

#include #include void main()

{

? ? inta =10;

? ? intb =5;

? ? intc =20;

? ? intd =15;

? ? boole =false;

? ? e = ((a > b)&&(c > d));

? ? printf("e = %d\n", e);

}? ?

  運行結(jié)果:e = 1。

  邏輯與 && 是用來連接表達式,表達式的結(jié)果是bool 值,好比上述例子,a > b 是true,c > d 是true,所以 true && true 的結(jié)果是true,得到 c 的值就為1。讀者可以自行修改,比如把 a > b 改為 a < b 得到的 c 是 false && true ,結(jié)果是false。所以邏輯與 && 只有三種可能兩種結(jié)果(不是true就是false):true && true 為 true,true && false 為 false, false && false 為 false。

? ? ? ? 同理,邏輯或 || ,true || true 為 true,true || false 為 true,false || false 為 false。

   邏輯非 !,加在表達式前,如果數(shù)值為0,結(jié)果為1;如果數(shù)值不為0,結(jié)果為0??梢詤⒖家韵麓a,

#include #include void main()

{

? ? inta =100;

? ? intb =0;

? ? intc = -10;

? ? intd =1000;

? ? d = !a;

? ? printf("d = %d\n", d);

? ? d = !b;

? ? printf("d = %d\n", d);

? ? d = !c;

? ? printf("d = %d\n", d);

}? ?

  運行后,d的值分別為:0,1,0。


? ? ? ?最后的最后講解一個非主流的運算符 sizeof? 。

? ? C語言學到后期,一般都會誤認為 sizeof 是個C庫的函數(shù),其實它是個運算符,用于計算變量或者字符串占用內(nèi)存的字節(jié)數(shù),代碼如下:

#include #include void main()

{

? ? inta =100000;

? ? charb =42;

? ? floatc =3.1415;

? ? boold =false;

? ? intresult = -1;

? ? result =sizeof(a);

? ? printf("result = %d\n", result);

? ? result =sizeof(b);

? ? printf("result = %d\n", result);

? ? result =sizeof(c);

? ? printf("result = %d\n", result);

? ? result =sizeof(d);

? ? printf("result = %d\n", result);

}? ?

  運行結(jié)果 result 的值依次為:4,1,4,1。這個結(jié)果剛好就是一個整型int占用字節(jié)數(shù)4,一個char占用字節(jié)數(shù)1,一個float占用字節(jié)數(shù)4,一個bool占用字節(jié)數(shù)1。


? 變量命名法

  本節(jié)最后講解兩種變量的命名方式,之前變量命名由于代碼比較短小,很容易就能理解代碼的意思,所以隨便用個a或者b就湊合著用了,但是如果要用C語言做個大一點的項目,也就是當代碼量很大的時候,變量名就需要人性化一些,便于多人一起維護項目,就像學生寫作文一樣,評卷老師看到字寫得好看,不管內(nèi)容如何,先給50分。


? 匈牙利命名法

  比如我要給的年齡的變量命名,首先采用的是 int 類型,在匈牙利命名規(guī)則中,整型一般用 i 或者 n ,

所以這么聲明變量:int nAge;


??其它命名法

  筆者在 linux 驅(qū)動代碼中選取了一個比較有代表性的變量命名:

注意:linux 驅(qū)動代碼幾乎都是用C語言完成的,驅(qū)動是用來驅(qū)動設備的,C語言在這方面有它的優(yōu)越性,比如位運算,指針操作等等。

int input_devices_state;

  一看就能明白這個變量的意義,表示輸入設備的狀態(tài)。


bool mutex_acquired;

  這個是互斥鎖請求,不明白單詞的意思可以用翻譯軟件。


int retval =0;

  ret 意思為 return ,val 意思為 value,組合起來 retval 就是返回值的意思,后續(xù)學函數(shù)就能明白返回值的作用了。


  本章終于完結(jié),撒花撒花!

自學C/C++不易,此路應攜手前行。

如果你想跟著小編一起學編程的話!

可以來我專欄的C語言/C++編程學習交流俱樂部,【點擊進入】!

還有(源碼,零基礎教程,項目實戰(zhàn)教學視頻),歡迎初學者和正在進階中的小伙伴們!? ? ?

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容