contributed by < kevinshieh0225
>
1
:bitwise average在 binary search 時需要取中間索引,而可能出現以下實作之探討。第一個程式碼明顯可能出現 (a+b) 導致 overflow 的問題,故通常會改以 (low) + (high - low) / 2 做取代
以 bitwise 操作改寫:
EXP1
= a & b & 1
再次改寫,這次我們用 bitwise 實作加法器原理:
EXP2
= a & b
EXP3
= a ^ b
2
:bitwise max讓我們從文件 That XOR Trick 切入:
EXP4
== a ^ b
EXP5
== a < b
我認為上面 max 函式應能使用在有號與無號的整數上。以下我們來看另一種實作。
我們參考〈解讀計算機編碼〉中 min
的實作原理:
回來看看有號整數的 max
的實作:
這種方法相比最初考試的版本還更好理解,但它卻有以下問題:
0x0000
與0xffff
的遮罩。(無號整數是邏輯右移)INT32_MIN <= (a - b) <= INT32_MAX
為前提,否則將導致位元溢出。3
: greatest common divisor以下是等價實作:
COND
= v
RET
= u << shift
__builtin_ctz
是 GCC 的內建函式,並非標準函式,但可在 GCC 編譯下加速位元運算的效率。參考 6.59 Other Built-in Functions Provided by GCC:
Built-in Function: int __builtin_ctz (unsigned int x)
Returns the number of trailing 0-bits in x, starting at the least significant bit position. If x is 0, the result is undefined.
__builtin_ctz
回傳從 LSB 數來的 0-bits 數量。這可以讓我們的程式碼更快速的掌握並除以 2 的倍數。
在 lib/math/gcd.c 中我們可以看到兩種 gcd 函式的實作版本,差異在系統定義的 CONFIG_CPU_NO_EFFICIENT_FFS
:是否 find first set __ffs
函式是可用的,若無就改以用 while 迴圈依序檢查處理。
以下我們針對使用 __ffs
的實作方式作探討:
__ffs 是在 linux/include/asm-generic/bitops/__ffs.h 中定義的函式:
舉個例子:
32 = 10000,__ffs(34ul) == 5
34 = 10010,__ffs(34ul) == 2
稍微了解它的功能後回來看到 gcd
程式碼中:
4
:bitset目的:消除最低位元的 1
bitset & -bitset 可以得出其他為 0,只剩最低位元之位置為 1
如:
bitset = 01001100
-bitset= 10110100
bitset & -bitset = 00000100
bitset ^ t = 01001000
EXP6
= bitset & -bitset
5
:166. Fraction to Recurring Decimal PPP
= pos--
MMM
= list_add
EEE
= &heads[remainder % size]
6
:__alignof__從文件中關於 __alignof__ 的描述:
The keyword alignof determines the alignment requirement of a function, object, or a type, or the minimum alignment usually required by a type. Its syntax is just like sizeof and C11 _Alignof.
在理解 ALIGNOF
的程式碼前,可以先來理解 offsetof macro
:
offsetof - wikipedia
C's offsetof() macro is an ANSI C library feature found in stddef.h. It evaluates to the offset (in bytes) of a given member within a struct or union type, an expression of type size_t.The offsetof() macro takes two parameters, the first being a structure name, and the second being the name of a member within the structure.
我對 offsetof()
的解釋如下:
0
轉型為 struct*
,這麼做是在給定一個起始地址在 0
的結構,以便後續對齊並得出該結構成員 memb
的地址位移 offset
。memb
並取其地址memb
和 0
的地址相減取得 offset
。在這裡可注意的是:我們先將地址轉型成 (char *)
後才執行運算,意思是我們以一個字節 (sizeof(char) = 1 byte)
作為單位來算 offset
。memb
在結構中的位置後回傳 size_t
型態的值。看懂以後我們就來解析 ALIGNOF
。
M
= _h
X
= 0
7
:Fizz BuzzFizz Buzz 的規則如下
我們若能精準從給定輸入 i 的規律去控制 start 及 length,即可符合 FizzBuzz 題意。
KK1
= div3
KK2
= div5
KK3
= div3 << 2