?? 第10章 位(bit)和字節(byte).txt
字號:
代替
#define A_FLAG 4096
#define A_FLAG 8192
這樣可以降低出錯的可能性。
宏SET_FLAG(N,F)能置位變量N中由值F指定的位,而宏CLR_FLAG(N,F)則剛好相反,它能清除變量N中由值F指定的位。宏TST_FLAG(N,F)可用來測試變量N中由值F指定的位,例如:
if (TST_FLAG (flags, A_FLAG))
/* do something * /;
宏BIT_RANGE(N,M)能產生一個與由N和M指定的位之間的位對應的屏蔽字,因此,你可以用
# define FIRST_OCTAL_DIGIT BIT_RANGE (0,2) /*111"/
# define SECOND-OCTAL-DIGIT BIT-RANGE(3,5) /* 111000*/
代替
#define FIRST_OCTAL_DIGIT 7 /*111*/
#define SECOND_OCTAL_DIGIT 56 /* 111000 * /
這樣可以更清楚地表示所需的位。
宏BIT_SHIFT(B,N)能將值B移位到適當的區域(從由N指定的位開始)。例如,如果你用標志C表示5種可能的顏色,你可以這樣來定義這些顏色:
#define C_FLAG BIT-RANGE(8,10) /* 11100000000 */
/* here are all the values the C flag can take on * /
# define C_BLACK BIT-SHIFTL(0,8) /* ooooooooooo */
# define C-RED BIT_SHIFTL(1,8) /* 00100000000 */
# define C-GREEN BIT_SHIFTL(2,8) /* 01000000000 */
# define C-BLUE BIT-SHIFTL(3,8) /* 01100000000 */
# define C_WHITE BIT-SHIFTL(4,8) /* 10000000000 */
# defineC-ZERO C-BLACK
# defineC-LARGEST C-WHITE
/* A truly paranoid programmer might do this */
#if C_LARGEST > C_FLAG
Cause an error message. The flag C_FLAG is not
big enough to hold all its possible values.
#endif /* C_LARGEST > C_FLAG */
宏SET_MFLAG(N,F,V)先清除變量N中由值F指定的位,然后置位變量N中由值V指定的位。宏CLR_MFLAG(N,F)的作用和CLR_FLAG(N,F)是相同的,只不過換了名稱,從而使處理多位標志的宏名字風格保持一致。宏GET_MFLAG(N,F)能提取變量N中標志F的值,因此可用來測試該值,例如:
if (GET_MFLAG(flags, C_FLAG) == C_BLUE)
/*do something */;
注意:宏BIT_RANGE()和SET_MFLAG()對參數N都引用了兩次,因此語句
SET_MFLAG(*x++,C_FLAG,C_RED);
的行為是沒有定義的,并且很可能會導致災難性的后果。
請參見:
10.1 用什么方法存儲標志(flag)效率最高?
10.3 位域(bit fields)是可移植的嗎?
10.3位域(bit fields)是可移植的嗎?
位域是不可移植的。因為位域不能跨越機器字,而且不同計算機中的機器字長也不同,所以一個使用了位域的程序在另一種計算機上很可能無法編譯。
假設你的程序能在另一種計算機上編譯,將位分配給位域時所遵循的順序仍然是沒有定義的。因此,不同的編譯程序,甚至同一編譯程序的不同版本所產生的代碼,很可能無法在由原來的編譯程序所生成的數據上工作。通常應該避免使用位域,除非計算機能直接尋址內存中的位并且編譯程序產生的代碼能利用這種功能,并且由此而提高的速度對程序的性能是至關重要的。
請參見:
10.1 用什么方法存儲標志(flag)效率最高?
10.2 什么是“位屏蔽(bit masking)”?
10.4 移位和乘以2這兩種方式中哪一種更好?
不管你采用哪種方式,任何合格的優化編譯程序都會產生相同的代碼,因此你可以采用使
程序的上下文更易讀的那種方式。你可以用DOS/Windows上的CODEVIEW或UNIX機上
的反匯編程序(通常被稱為"dis”)這樣的工具來查看下述程序的匯編代碼:
例10.4乘以2和左移一位經常是相同的
void main()
{
unsigned int test_nbr = 300;
test_nbr * =2;
test_nbr = 300;
test_nbr << = 1;
}
請參見:
10.1 用什么方法存儲標志(flag)效率最高?
10.5 什么是高位字節和低位字節?
通常我們從最高有效位(most significant digit)開始自左向右書寫一個數字。在理解有效位這個概念時,可以想象一下你的支票數額的第一位增加1和最后一位增加1之間的巨大區別,前者肯定會讓你喜出望外。
計算機內存中一個字節的位相當于二進制數的位,這意味著最低有效位表示1,倒數第二個有效位表示2×1或2,倒數第三個有效位表示2×2×1或4,依此類推。如果用內存中的兩個字節表示一個16位的數,那么其中的一個字節將存放最低的8位有效位,而另一個字節將存放最高的8位有效位,見圖10.5。存放最低的8位有效位的字節被稱為最低有效位字節或低位字節,而存放最高的8位有效位的字節被稱為最高有效位字節或高位字節。
高位字節 低位字節
↓--------------------------↓ ↓---------------------------↓
15 14 13 12 11 10 9. 8. 7. 6. 5. 4. 3. 2. 1. 0.
圖 10.5 雙字節整數中的位
請參見:
10. 6 16位和32位的數是怎樣存儲的
10.6 16位和32位的數是怎樣存儲的?
一個16位的數占兩個字節的存儲空間,即高位字節和低位字節(見10.5中的介紹)。如果你是在紙上書寫一個16位的數,你總是會把高位字節寫在前面,而把低位字節寫在后面。然而,當這個數被存儲到內存中時,并沒有固定的存儲順序。
如果我們用M和L分別表示高位字節和低位字節,那么可以有兩種方式把這兩個字節存儲到內存中,即M在前L在后或者L在前M在后。把M存儲在前的順序被稱為“正向(forward)”或“高位優先(big—endian)”順序;把L存儲在前的順序被稱為“逆向(reverse)”或“低位優先(little—endian)”順序。
big—endian這個術語的含義是數的“高位(big end)”存儲在前,同時這也是對《Gulliver'sTravels》這本書中的一個詞的引用,在該書中big—endian一詞是指那些從大頭開始吃一個煮雞蛋的人。
大多數計算機按正向順序存儲一個數,Intel CPU按逆向順序存儲一個數,因此,如果試圖將基于Intel CPU的計算機連到其它類型的計算機上,就可能會引起混亂。
一個32位的數占4個字節的存儲空間,如果我們按有效位從高到低的順序,分別用Mm,Ml,Lm和Ll表示這4個字節,那么可以有4!(4的階乘,即24)種方式來存儲這些字節。在過去的這些年中,人們在設計計算機時,幾乎用遍了這24種方式。然而,時至今天,只有兩種方式是最流行的,一種是(Mm,MI,Lm,LD,也就是高位優先順序,另一種是(Ll,Lm,Ml,Mm),也就是低位優先順序。和存儲16位的數一樣,大多數計算機按高位優先順序存儲32位的數,但基于Intel CPU的計算機按低位優先順序存儲32位的數。
請參見:
10.5什么是高位字節和低位字節?
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -