今天看到一個有趣的知識點,趕緊記錄一下,眾所周知,C 語言沒有泛型,但是 C11 新增了一種表達式,叫做泛型選擇表達式 (_ Generic),這個是幹啥的呢?它的作用是根據表達式的類型選擇一個值,讓我們來看一看它具體的語法
泛型選擇引入#
先看一段代碼:
int main()
{
int x = 1;
double y = 2.0;
char z = 'c';
printf("%d\n", _Generic(x, int:0, double : 1, default:3));
printf("%d\n", _Generic(y, int:0, double : 1, default:3));
printf("%d\n",_Generic(z, int:0, double : 1, default:3));
return 0;
}
_Generic是C11關鍵字,後面的圓括號中包含有多個用逗號分隔的項,第一個項是表達式,後面的每一個項都由一個類型、一個冒號和一個值組成,如double: 1。第一個項的類型匹配哪一個標籤,整個表達式的值就是該標籤後面的值
運行結果如下:
可以看到,根據傳入的變量的類型,打印的結果也不同,第一個 printf 的第一項 x 是 int,那麼整個表達式的結果為 0,第二個 printf 的第一項是 double,表達式的結果就是 1,第三個 printf 打印結果為 3 是因為 char 類型沒有匹配,走了默認的 default,結果為 3
其實,這個東西很像 switch 語句,只是 Generic 用表達式類型匹配標籤,switch 用表達式的值匹配標籤
與宏定義組合#
我們可以看到啊,上邊的用法還是比較惡心麻煩的,但是呢,我們可以結合宏定義組合去玩這個東西,這樣就會非常的方便
直接看例子:
#define MYTYPE(X) _Generic((X),int:"int", double:"double", default:"other")
int main()
{
int d = 2;
printf("%s\n", MYTYPE(d));
printf("%s\n", MYTYPE(1.0*d));
printf("%s\n", MYTYPE("string"));
return 0;
}
運行結果如下:
與宏定義結合是不是感覺好多了,甚至有點 C++ 泛型編程的感覺了,但是其實還差點。
進階玩法#
_Generic 標籤對應的值,可以是整型,也可以是字符串,當然也可以是函數指針。
我們來看一下下邊的這段代碼。
void PrintInt(int x)
{
printf("%d\n", x);
}
void PrintDouble(double x)
{
printf("%lf\n", x);
}
void PrintSting(char* x)
{
printf("%s\n", x);
}
void PrintOther(void x)
{
print("類型有點問題\n");
}
#define PRINT(X) _Generic((X),\
int:PrintInt,\
double:PrintDouble,\
const char*:PrintSting,\
default:PrintOther)(X)
int main()
{
int x = 1;
int y = 2.0;
const char* str = "hello _Generic";
PRINT(x);
PRINT(y);
PRINT(str);
return 0;
}
運行結果如下:
這樣是不是和 C++ 的泛型編程很像了呢,是不是挺有意思的,當然還是 C++ 的泛型好用一些。