C語言學習筆記 C之神奇的移位運算子

2021-10-10 22:13:32 字數 1382 閱讀 3852

到目前為止,雖然知道有這麼個運算子存在,但其實我並沒有真正用過移位運算子。對於大部分題目而言和我目前的水平所能接觸的範圍有限的原因,我覺得移位運算子沒有什麼太大用處,感覺很雞肋。

但上週的月賽卻死在了這道「簽到題」上面。

問題是將乙個10000以內的數算術右移i位(i<=100000).

我想著c中的》運算子不就是算術右移運算子嗎?

這也太簽到了吧!

但…其中的問題是,對於右移很多位的情況下答案就不正確。

想來想去我也不知道問題所在。

最後還是回來查閱資料才清楚

對於c而言,對常量進行移位操作不會出現上述原因,但對變數就會出現問題。

根本原因是c在設計》運算子之初定下的規矩

首先我們先了解下右移運算子的百科定義

左移運算是將乙個二進位制位的運算元按指定移動的位數向左移位,移出位被丟棄,右邊的空位一律補0。右移運算是將乙個二進位制位的運算元按指定移動的位數向右移動,移出位被丟棄,左邊移出的空位或者一律補0,或者補符號位,這由不同的機器而定。在使用補碼作為機器數的機器中,正數的符號位為0,負數的符號位為1。(均由機器來定:這個不正確)(msdn原文明確說明,右移對於無符號型別強制補0,對於有符號型別續補符號位)

百科還以左移為例子解釋了上述現象的原因

左移裡乙個比較特殊的情況是當左移的位數超過該數值型別的最大位數時,編譯器會用左移的位數去模型別的最大位數,然後按餘數進行移位,如:

int i = 1, j = 0x80000000; //設int為32位

i = i << 33; // 33 % 32 = 1 左移1位,i變成2

j = j << 33; // 33 % 32 = 1 左移1位,j變成0,最高位被丟棄

在用gcc編譯這段程式的時候編譯器會給出乙個warning,說左移位數》=型別長度.那麼實際上i,j移動的就是1位,也就是33%32後的餘數.在gcc下是這個規則,別的編譯器是不是都一樣還不清楚.

然而實際上我們知道對1左移33位的結果應該是0,但由於編譯器的特點導致了結果的「錯誤」。

故對於右移而言.同樣當移動的位數超過型別的長度時,會取餘數,然後移動餘數個位.

那麼要如何才能解決這個問題呢?

一開始我想到的就是判斷這個數字到第幾位了 然後右移超過這個位數就自動輸出0,的確,這是個可行的辦法,但有點太冗長和繁瑣了。

想著翻閱一些資料看看有沒有更加簡便的方法,但無論在國內搜尋還是翻牆國外搜尋大多**的還是c中》運算子到底是算術還是邏輯以及一些特性(比如移動位數越界時),找了一圈都沒有人側重於討論這個問題。

C語言學習筆記

include include void swap int p1,int p2 void swapa int arr,int n void printfa int arr,int n int main int argc,char argv swap i,j printfa array,6 swapa...

C語言學習筆記

file 結構 包含在stdio.h裡 ifndef file defined struct iobuf typedef struct iobuf file define file defined endif fread 功 能 從乙個流中讀資料 函式原型 size t fread void buf...

C語言學習筆記

我們學習c語言最開始入門的時候,都是先從c語言學習 c語言教材書籍開始學習,這些是我摘要的一些內容。第一章 c 語言概述 語言概述 1.1 物件導向程式設計基本概念 1.2 c 語言是一種物件導向的程式設計 語言 1.3 c 程式結構的特點 程式結構的特點 1.4 visual c 6.0簡介 簡介...