芝士就是菜

芝士就是菜

公众号 芝士就是菜
zhihu
bilibili
youtube
twitter
github
email

震驚!!!C語言也能實現泛型編程嗎??

今天看到一個有趣的知識點,趕緊記錄一下,眾所周知,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。第一個項的類型匹配哪一個標籤,整個表達式的值就是該標籤後面的值

運行結果如下:

image.png

可以看到,根據傳入的變量的類型,打印的結果也不同,第一個 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;
}

運行結果如下:

image.png

與宏定義結合是不是感覺好多了,甚至有點 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;
}

運行結果如下:
image.png

這樣是不是和 C++ 的泛型編程很像了呢,是不是挺有意思的,當然還是 C++ 的泛型好用一些。

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。