這應該也算是一種 Pattern?
會想特別學習補充這些 Macro 除了本身做嵌入式系統,常寫 C 之外,還有前陣子去面試 NVIDIA System Software 被考了以下某一個 Macro 的實作...
所以認真看待各種巨集也是很重要的
Preprocessor operators
Statement expressions
// 很多 IC 廠軟韌必考這些 Bitwise 操作哦
#define SET_BIT(var, bit) ((var) |= (1 << (bit))) // 用於設置變量中的特定位
#define CHECK_BIT(var, bit) ((var) & (1 << (bit))) // 用於檢查變量中的特定位是否設置
#define CLEAR_BIT(var, bit) ((var) &= ~(1 << (bit))) //用於清除變量中的特定位
#define TOGGLE_BIT(var, bit) ((var) ^= (1 << (bit))) // 用於切換變量中的特定位
// 數學類,想要再進階點可以思考,遇到不同 Type 時可以如何優化?
#define ABS(x) ((x) < 0 ? -(x) : (x)) // 用於計算數字的絕對值
#define MAX(a, b) ((a) > (b) ? (a) : (b)) // 用於找出兩個數字中的最大值
#define MIN(a, b) ((a) < (b) ? (a) : (b)) // 用於找出兩個數字中的最小值
// 基本操作類
#define SWAP(a, b) do { a ^= b; b ^= a; a ^= b; } while (0)
#define UNUSED(x) (void)(x) // 用於標記未使用的變量,以避免編譯器警告
// 字串類,常跟 print, uart, logging...之類的功能並用
#define STR(x) #x // 用於將 Macro 參數轉換為字串
#define CONCAT(a, b) a ## b // 用於連接兩個 Macro 參數
#define BIT(nr) (1UL << (nr))
/* &a[0] degrades to a pointer: a different type from an array */
#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
#define SAFE_MALLOC(size) \
({ void *ptr = malloc(size); \
if (!ptr) { \
perror("Memory allocation failed"); \
exit(EXIT_FAILURE); \
} \
ptr; })
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
// 告訴編譯器 a == 2 不容易發生,可以優化 Assembly 的 jump 指令
if (unlikely (a == 2))
a++;
else
a--;
#define list_entry(ptr, type, member) \
container_of(ptr, type, member)
#define list_for_each_entry(pos, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member); \
&pos->member != (head); \
pos = list_entry(pos->member.next, typeof(*pos), member))
#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
#define WARN_ON(condition) (unlikely((condition)) ? WARN_ON__ : 0)
#define READ_ONCE(x) (*(volatile typeof(x) *)&(x))
#define WRITE_ONCE(x, val) do { (*(volatile typeof(x) *)&(x)) = (val); } while (0)
#define rcu_dereference(p) ({ \
typeof(*p) *_________p1 = READ_ONCE(p); \
smp_read_barrier_depends(); \
(_________p1); \
})
#define spin_lock(lock) _raw_spin_lock(lock)
#define spin_unlock(lock) _raw_spin_unlock(lock)
// 記得 #include <time.h>
#define MEASURE_TIME(expr) \
({ clock_t start = clock(); \
expr; \
clock_t end = clock(); \
double elapsed = ((double) (end - start)) / CLOCKS_PER_SEC; \
elapsed; })