typedef struct cmd_tbl_s cmd_tbl_t;
#define Struct_Section __attribute__ ((unused,section(".cli_cmd")))
#define REGISTER_CMD(name, maxargs,handler, usage) \
const cmd_tbl_t cli_cmd_##name Struct_Section = {#name, maxargs ,handler , usage}
uj5u.com熱心網友回復:
謝邀。這段代碼不復雜,宏定義你也不陌生吧。重點在于__attribute__、#和##
#和##也不難,這是C語言的前處理器記號,你也應該知道。
因此,你的問題主要是__attribute__。這個記號并不是C語言的記號,而是GCC自行擴展的記號。翻一下GCC的手冊:https://gcc.gnu.org/onlinedocs/10.2.0/ 或者上網搜索一下,這里就不再羅索了。
uj5u.com熱心網友回復:
#與##在宏定義中的--宏展開#include <stdio.h>
#define f(a,b) a##b
#define g(a) #a
#define h(a) g(a)
int main()
{
printf("%s\n", h(f(1,2))); // 12
printf("%s\n", g(f(1,2))); // f(1,2)
return 0;
}
宏展開時:
如果宏定義以#開頭,不展開引數,直接替換。
故g(f(1,2))--->#f(1,2)--->"f(1,2)";
如果宏定義不以#開頭,展開引數,直接替換,由外層向里層,如果碰到的是#開頭的宏,不繼續往里層展開,往外層展開。
由外層向里層,如果碰到的是以非#開頭的宏,繼續往里層走,直至最里層,開始一層層往外層展開。
故h(f(1,2))--->h(12)--->g(12)---->#12----->"12"。
PS:
##在宏中定義,是字符連接符
如a##b##c 等同于 "abc"
#在宏開頭出現,是表示宏展開的方式不同
#a 等同于"a"
#abc 等同于 "abc"
復雜的:
#include <stdio.h>
#define f(a,b) a##b
#define g(a) #a
#define h(a) g(a)
int main()
{
char a = 'a';
cout<<g(a)<<endl; // a
cout<<g(g(a))<<endl; // a
printf("%s\n", h(f(1,2))); // 12
printf("%s\n", g(f(1,2))); // f(1,2)
printf("%s\n", g(h(f(1,2)))); // h(f(1,2))
printf("%s\n", h(g(f(1,2)))); // "f(1,2)"
printf("%s\n", h(h(f(1,2)))); // "12"
system("pause");
return 0;
}
預處理后的:(在編譯選項中添加/EP /P后編譯生成的.i檔案。gcc加-E)
int main()
{
char a = 'a';
cout<<"a"<<endl;
cout<<"g(a)"<<endl;
printf("%s\n", "12");
printf("%s\n", "f(1,2)");
printf("%s\n", "h(f(1,2))");
printf("%s\n", "\"f(1,2)\"");
printf("%s\n", "\"12\"");
system("pause");
return 0;
}
---------------------------------------------------
宏決議
1. ##運算子
##運算子它的作用是在替代表中將其前后的引數連接成為一個預處理符號,它不能出現于宏替代表的開端和末尾。
例:
#define concat(s,t) s##t
#define AAA ABC
concat(A, AA)
將被替換成
ABC
2. 重新掃描和替換
在替換串列中的所有引數替換過之后,前處理器將對結果token序列重新掃描以便對其中的宏再次替換。
當正在替換的宏在其替換串列中發現自身時,就不再對其進行替換。在任何正在嵌套替換的宏的替換程序中遇到正被替換的宏就對其不再進行替換(防止遞回)。
例:
#define ROOT AAA CCC
#define AAA ROOT
ROOT
將被替換成
ROOT CCC
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/9539.html
標籤:C語言
