contributed by < Duodenum >
1
在 Linux 核心原始程式碼,include/linux/bitfield.h 提及一個巨集 GENMASK,其作用是依據給定的範圍,產生連續的 bitmask
輸入為 h, l 合理推斷為兩段 bitset 最後 & 出所求,兩段分別為 h 到 LSB
以及 l 到 MSB
。 例如: 000111112 & 111100002 = 000100002
因為 UL 為 64 bits , (~0UL) 需要右移 64 - 1 - h
bits ,LEFT
= 63 - h
而後者先右移 l
後再左移 l
後即可將後 l
bits 設為 0
, RIGHT
= l
2
由上方 fd
結構體可知 EXP1
前綴應為 (struct foo *)
指向 foo
的指標
因題目要求做 4 byte alignment ,其指標位址需要可以整除 4 ,也就是說最後的兩個 bit 清零。 再根據題目中的 flags
給予靈感,直接 v & ~3
即可達到此效果。 EXP1
= (struct foo *)(v & ~3)
3
考慮以下程式碼,能將輸入的 8 位元無號整數逐一位元反轉,如同 LeetCode 190. Reverse Bits 的描述。
第一行相當直觀將 8-bit 分為前後兩段,並且前後交換
第二行中 0xCC
= 110011002 ,可以看出為了將 1 與 0 位置交換,所以可以仿照其寫出 (EXP2)
為 001100112 再左移 2bit , EXP2
= (x & 0x33) << 2
第三行則再細切成相鄰兩位元交換,如同 0xAA
= 101010102 。EXP3
取 010101012 再左移 1bit , EXP3
= (x & 0x55) << 1
4
嘗試將 foreach 巨集 予以擴充,使得支援以下寫法:
其中的巨集定義為:
TODO
5
針對 LeetCode 29. Divide Two Integers,以下是可能的實作:
前兩個 if 迴圈分別判斷除數與被除數的正負,如其中有負數,則以 signal
紀錄之,並將負數取絕對值以實現除法。接下來的演算法概念則與長除法相似,首先將除數提高至被除數的最高位數,再逐位數算出商數。第一個 while 迴圈就是在做提高位數的部分,其判斷式即為將除數乘上 2 的冪直到大魚被除數為止, EXP6
= dvs << shift
。
第二個 while 迴圈即為對每個位數計算對映的商,並將被除數減去所消去之值, EXP7
= dvd -= dvs << shift
。
6
針對 LeetCode 149. Max Points on a Line,以下是可能的實作:
TODO
7
考慮 ilog32 函式可針對給定的 32 位元無號數,計算扣除開頭的 0,最少需要多少位元才可儲存 (the minimum number of bits required to store an unsigned 32-bit value without any leading zero bits),以下是一個可能的實作: