?
Dokumen ini menggunakan Manual laman web PHP Cina Lepaskan
提供了一種在編譯時(shí)根據(jù)控制表達(dá)式的類(lèi)型選擇多個(gè)表達(dá)式之一的方法。
_Generic ( controlling-expression , association-list ) | (since C11) |
---|
其中關(guān)聯(lián)列表是以逗號(hào)分隔的關(guān)聯(lián)列表,每個(gè)關(guān)聯(lián)列表都有語(yǔ)法。
type-name : expression | ||
---|---|---|
default : expression |
其中
類(lèi)型名 | - | 任何未經(jīng)可變修改的完整對(duì)象類(lèi)型(即不是VLA或指向VLA的指針)。 |
---|---|---|
控制表達(dá) | - | 如果不使用默認(rèn)關(guān)聯(lián),則其類(lèi)型必須與其中一個(gè)類(lèi)型名稱(chēng)兼容的任何表達(dá)式(逗號(hào)運(yùn)算符除外) |
表達(dá) | - | 任何類(lèi)型和值類(lèi)別的任何表達(dá)式(逗號(hào)運(yùn)算符除外) |
關(guān)聯(lián)列表中沒(méi)有兩個(gè)類(lèi)型名稱(chēng)可以指定兼容類(lèi)型??赡苤挥幸粋€(gè)關(guān)聯(lián)使用關(guān)鍵字default
。如果default
沒(méi)有使用,并且沒(méi)有任何類(lèi)型名稱(chēng)與控制表達(dá)式的類(lèi)型兼容,程序?qū)⒉粫?huì)編譯。
控制表達(dá)式的類(lèi)型(在適用的情況下應(yīng)用左值轉(zhuǎn)換后(如果支持,請(qǐng)參閱下面的注釋?zhuān)┡c關(guān)聯(lián)列表中的類(lèi)型名稱(chēng)進(jìn)行比較。
如果類(lèi)型與其中一個(gè)關(guān)聯(lián)的類(lèi)型名稱(chēng)兼容,則泛型選擇的類(lèi)型,值和值類(lèi)別是出現(xiàn)在該類(lèi)型的冒號(hào)后面的表達(dá)式的類(lèi)型,值和值類(lèi)別 - 名稱(chēng)。
如果沒(méi)有任何類(lèi)型名稱(chēng)與控制表達(dá)式的類(lèi)型兼容,并且default
提供了關(guān)聯(lián),則泛型選擇的類(lèi)型,值和值類(lèi)別是表達(dá)式之后的類(lèi)型,值和值類(lèi)別該default :
標(biāo)簽。
控制表達(dá)式和未選擇的選擇表達(dá)式從不被評(píng)估。
控制表達(dá)式的左值轉(zhuǎn)換仍然是一個(gè)未解決的問(wèn)題(DR 431 / n1930):clang 不執(zhí)行它們并按照原樣使用左值的類(lèi)型:"abc"
匹配char[4]
而不是char*
,(int const){0}
匹配const int
而不是int
)。同時(shí),gcc執(zhí)行控制表達(dá)式的左值轉(zhuǎn)換(僅在類(lèi)型域中:它放棄了頂級(jí)cvr限定符和原子性,或者將數(shù)組應(yīng)用于控制表達(dá)式類(lèi)型的指針/函數(shù)指針轉(zhuǎn)換,而不啟動(dòng)任何副作用或計(jì)算任何值)。對(duì)于 GCC,"abc"
匹配char*
和char[4]
和(int const){0}
的比賽int
,而不是const int
。
所有值類(lèi)別(包括函數(shù)指示符和無(wú)效表達(dá)式)都可以在通用選擇中作為表達(dá)式使用,如果選擇了,則通用選擇本身具有相同的值類(lèi)別。
<tgmath.h>
在 C99中引入的類(lèi)型通用數(shù)學(xué)宏以編譯器特定的方式實(shí)現(xiàn)。在 C11中引入的通用選擇為程序員提供了編寫(xiě)類(lèi)似類(lèi)型相關(guān)代碼的能力。
泛型選擇類(lèi)似于C ++中的重載(其中幾個(gè)函數(shù)中的一個(gè)是在編譯時(shí)根據(jù)參數(shù)的類(lèi)型選擇的),除了它在任意表達(dá)式之間進(jìn)行選擇之外,與函數(shù)重載不同,函數(shù)可能具有不同的返回類(lèi)型,甚至不同的價(jià)值類(lèi)別。
_Generic
, default
.
#include <stdio.h>#include <math.h> // Possible implementation of the tgmath.h macro cbrt#define cbrt(X) _Generic((X), \ long double: cbrtl, \ default: cbrt, \/*for clang*/ const float: cbrtf, \ float: cbrtf \)(X) int main(void){ double x = 8.0; const float y = 3.375; printf("cbrt(8.0) = %f\n", cbrt(x)); // selects the default cbrt printf("cbrtf(3.375) = %f\n", cbrt(y)); // gcc: converts const float to float, // then selects cbrtf // clang: selects cbrtf for const float}
輸出:
cbrt(8.0) = 2.000000cbrtf(3.375) = 1.500000