[英]C Makefile commands
我試圖構建一個 C 項目,它有一種相當陌生的方式來定義命名空間,例如。 在文件 root.h 中
#define eval CRYPTO_NAMESPACE(eval)
在 Makefile 中出現以下內容(make all 的規則):
gcc -O3 -g -march=native -mtune=native -Wall -I. -Isubroutines -DKAT -DKATNUM='cat KATNUM' "-DCRYPTO_NAMESPACE(x)=x" "-D_CRYPTO_NAMESPACE(x)=_##x" -o kat nist/kat_kem.c nist/rng.c benes.c bm.c controlbits.c decrypt.c encrypt.c gf.c operations.c pk_gen.c root.c sk_gen.c synd.c transpose.c util.c -I${PWD}/subroutines -L${PWD}/libs/ -lXKCP -lcrypto -ldl
這些選項有什么作用:
"-DCRYPTO_NAMESPACE(x)=x" "-D_CRYPTO_NAMESPACE(x)=_##x"
我知道-DXXX=YYY
與#define XXX YYY
相同。 現在,為什么是雙引號? 為什么它看起來像一個宏(可能是)? 最后, _##x
是什么意思?
標題中的宏:
#define eval CRYPTO_NAMESPACE(eval)
用CRYPTO_NAMESPACE(eval)
替換每個令牌eval
。 所以如果代碼包含
void eval(char *expr) {
...
預處理器輸出 - 沒有任何其他定義 - 將是
void CRYPTO_NAMESPACE(eval)(char *expr) {
...
-D
參數有效地添加了另外兩個定義:
#define DCRYPTO_NAMESPACE(x) x
#define _CRYPTO_NAMESPACE(x) _##x
在我們的例子中,第一個define
導致正常結果被再次重寫:
void eval(char *expr) {
...
所以我們又回到了起點。 可以使用不同的定義來更改函數的編譯名稱。 此定義使標頭定義成為空操作。
第二個宏使用標記連接運算符##
。 它將前綴下划線_
添加到宏參數。 例如,如果代碼包含以下內容:
void _CRYPTO_NAMESPACE(foo)(int x) {
那么結果是
void _foo(int x) {
在更高的層次上,這些宏允許在整個程序中統一轉換事物的名稱(在第一種情況下,任何名為eval
東西,在第二種情況下,根本沒有任何名稱)。 對於大型 C 程序中的名稱沖突,這是一個相當標准的解決方法。 如果您有兩個源代碼庫都定義了相同的公共函數名稱,則可以使用這樣的宏添加前綴或后綴,從而更改編譯代碼中的一個或兩個名稱,而無需修改任一原始代碼。 這是長期配置管理的一項重要功能,其中手動編輯外部提供的代碼庫不是一個嚴肅的選擇。
一個瘋狂的猜測是,這種處理被給予eval
因為其他一些 C 代碼塊也定義了一個名為eval
的函數的可能性非常高。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.