linux2022
目的: 檢驗學員對 記憶體管理、對齊及硬體特性, 指標, bitwise, 前置處理器 的認知
作答表單: 測驗 1-8 (Linux 核心設計)
作答表單: 測驗 9-11 (Linux 核心實作)
1
在 Linux 核心原始程式碼,include/linux/bitfield.h 提及一個巨集 GENMASK
,其作用是依據給定的範圍,產生連續的 bitmask,例如:
GENMASK(6, 4)
產生 011100002GENMASK(39, 21)
產生 0x000000ffffe00000 (64 位元)已知我們使用的微處理器架構為 64 位元,且 unsigned long
為 8 位元組寬度 (符合 LP64 資料模型),以下是可能的 GENMASK
巨集的定義:
請補完,使其行為符合預期。作答規範:
LEFT
和 RIGHT
應以最簡潔的形式撰寫,且符合作業一排版規範 (近似 Linux 核心程式碼排版風格)LEFT
和 RIGHT
皆為表示式,可能包含常數LEFT
和 RIGHT
皆不該包含小括號 (即 (
和 )
)作答區
延伸問題:
GENMASK
巨集的實作,闡述其額外的考量GENMASK
巨集和 include/linux/bitfield.h 的應用案例2
考慮以下程式碼:
函式 fo_fd
接受指定的地址 v
,填入一個 fd
結構體,並確保第一個成員的地址得以依據〈你所不知道的 C 語言:記憶體管理、對齊及硬體特性〉描述,對 4 個位元組進行向下對齊 (即 C++ Boost 描述的 align_down)。其中 struct foo;
運用〈你所不知道的 C 語言:指標篇〉提及的 forward declaration 技巧,可在實作階段才提供具體 struct foo
的定義。
請補完,使其行為符合預期。作答規範:
EXP1
應以最簡潔的 C99 形式撰寫,符合作業一排版規範,且不該觸發編譯器警告訊息EXP1
不得使用 %
(modulo) 運算子v | 1
作答區
EXP1
= ?延伸問題:
3
考慮以下程式碼,能將輸入的 8 位元無號整數逐一位元反轉,如同 LeetCode 190. Reverse Bits 的描述。
請補完,使其行為符合預期。作答規範:
EXP2
和 EXP3
應以最簡潔的 C99 形式撰寫,符合作業一排版規範,且不該觸發編譯器警告訊息v | 1
作答區
EXP2
= ?EXP3
= ?延伸問題:
4
延伸〈你所不知道的 C 語言:前置處理器應用篇〉,我們嘗試將 foreach 巨集 予以擴充,使得支援以下寫法:
預期輸出如下:
對應的巨集定義:
請補完,使其行為符合預期。作答規範:
EXP4
和 EXP5
應以最簡潔的 C99 形式撰寫,符合作業一排版規範,且不該觸發編譯器警告訊息(
和 )
)作答區
EXP4
= ?EXP5
= ?延伸問題:
5
針對 LeetCode 29. Divide Two Integers,以下是可能的實作:
請補完,使其行為符合預期。作答規範:
EXP6
和 EXP7
應以最簡潔的 C99 形式撰寫,符合作業一排版規範,且不該觸發編譯器警告訊息(
和 )
)作答區
EXP6
= ?EXP7
= ?延伸問題:
6
針對 LeetCode 149. Max Points on a Line,以下是可能的實作:
請補完,使其行為符合預期。作答規範:
EXP8
和 EXP9
應以最簡潔的 C99 形式撰寫,符合作業一排版規範,且不該觸發編譯器警告訊息EXP8
不該出現小括號 (即 (
和 )
)EXP9
為包含 list_
開頭巨集的單一敘述作答區
EXP8
= ?EXP9
= ?延伸問題:
7
考慮 ilog32
函式可針對給定的 32 位元無號數,計算扣除開頭的 0
,最少需要多少位元才可儲存 (the minimum number of bits required to store an unsigned 32-bit value without any leading zero bits),以下是一個可能的實作:
請補完,使其行為符合預期。作答規範:
EXP10
和 EXP11
應以最簡潔的 C99 形式撰寫,符合作業一排版規範,且不該觸發編譯器警告訊息EXP11
不該出現小括號 (即 (
和 )
)EXP10
和 EXP11
皆包含 >
運算子作答區
EXP10
= ?EXP11
= ?延伸問題:
ilog
ilog2
實作8
考慮以下 C++ 二元搜尋樹的程式:
函式 remove_data
嘗試將指定的資料,自給定的二元搜尋樹移除,但原本的 remove_data
過於冗長,於是我們可善用 indirect pointer 改寫為以下:
請補完,使其行為符合預期。作答規範:
EXP12
, EXP13
和 EXP14
應以最簡潔的 C99 形式撰寫,符合作業一排版規範,且不該觸發編譯器警告訊息,並善用 indirect pointer 的技巧來撰寫EXP12
, EXP13
和 EXP14
皆不該出現 ;
作答區
EXP12
= ?EXP13
= ?EXP14
= ?延伸問題:
9
考慮以下進行記憶體地址對齊 (alignment) 的巨集:
作用是向上對齊 (roundup),請補完程式碼,使其行為符合預期。作答規範:
MMM
是常數NNN
是表示式MMM
和 NNN
皆不得出現小括號 (即 (
和 )
)作答區
MMM
= ?NNN
= ?延伸問題:
ROUND_DOWN
巨集10
考慮以下巨集可得到二個表示式進行整數除法操作時,最接近的整數值:
注意: 當除數 (即 divisor
) 為負值時,行為沒有定義。
參考執行結果:
DIVIDE_ROUND_CLOSEST(7, 3) = 2
DIVIDE_ROUND_CLOSEST(6, 3) = 2
DIVIDE_ROUND_CLOSEST(5, 3) = 2
作答規範:
RRR
和 SSS
為表示式,且都包含 (__x)
和 (__d)
(注意小括號)RRR
和 SSS
限用 +
, -
, >>
, <<
這幾個運算子,可搭配小括號,並以符合 C99 的最精簡形式撰寫RRR
和 SSS
出現的順序 (從左到右),必定是 __x
先於 __d
請補完程式碼,使其行為符合預期。
作答區
RRR
= ?SSS
= ?延伸問題:
11
考慮以下計算整數開平方根的實作:
i_sqrt
函式的作用等同於 floor(sqrt(x))
作答規範:
XXX
, YYY
和 ZZZ
都是敘述,不得呼叫任何函式,且不包含 ;
字元=
, +=
, -=
, >>=
, <<=
等運算子,且不得出現小括號 (即 (
和 )
)作答區
XXX
= ?YYY
= ?ZZZ
= ?延伸問題: