Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Ключевое слово _Generic используется для написания кода, который выбирает выражение во время компиляции в зависимости от типа аргумента. Это похоже на перегрузку в C++, при которой по типу аргумента выбирается вызываемая функция. В нашем случае тип аргумента выбирает выражение для вычисления.
Например, выражение _Generic(42, int: "integer", char: "character", default: "unknown"); оценивает тип 42 и ищет соответствующий тип int в списке. При обнаружении типа возвращается "integer".
Синтаксис
generic-selection:
_Generic
(assignment-expression, assoc-list)
assoc-list:
association
assoc-list, association
association:
type-name : assignment-expression
default : assignment-expression
Первое выражение assignment-expression называется управляющим. Тип управляющего выражения определяется во время компиляции и сопоставляется с assoc-list, чтобы найти выражение для вычисления и возврата. Само управляющее выражение не вычисляется. Например, при наличии _Generic(intFunc(), int: "integer", default: "error");intFunc не вызывается во время выполнения.
Когда определяется тип управляющего выражения, const, volatile и restrict удаляются перед сопоставлением с assoc-list.
Записи в assoc-list, которые не были выбраны, не вычисляются.
Ограничения
-
assoc-listне может указывать один и тот же тип более одного раза. -
assoc-listне может указывать типы, совместимые друг с другом, например перечисление и базовый тип этого перечисления. - Если при выборе _Generic нет значения по умолчанию, управляющее выражение должно иметь только одно совместимое имя типа в списке универсальных связей.
Пример
Как один из вариантов, _Generic можно использовать в макросе. Файл заголовка <tgmath.h> использует _Generic для вызова правильной математической функции в зависимости от типа аргумента. Например, макрос для cos сопоставляет вызов, содержащий число с плавающей точкой, с cosf, одновременно сопоставляя вызов, содержащий сложное число двойной точности, с ccos.
В приведенном ниже примере показано, как написать макрос, который определяет тип переданного в него аргумента. Если в "unknown" нет записей, совпадающих с управляющим выражением, создается assoc-list:
// Compile with /std:c11
#include <stdio.h>
/* Get a type name string for the argument x */
#define TYPE_NAME(X) _Generic((X), \
int: "int", \
char: "char", \
double: "double", \
default: "unknown")
int main()
{
printf("Type name: %s\n", TYPE_NAME(42.42));
// The following would result in a compile error because
// 42.4 is a double, doesn't match anything in the list,
// and there is no default.
// _Generic(42.4, int: "integer", char: "character"));
}
/* Output:
Type name: double
*/
Требования
Выполните сборку с помощью /std:c11.
Пакет Windows SDK 10.0.20348.0 (версия 2104) или выше. Скачать последнюю версию Windows SDK можно здесь. Инструкции по установке и использованию пакета SDK для разработки C11 и C17 см. в статье Включение поддержки C11 и C17 в Visual Studio.
См. также
/std (определение стандартной версии языка)
Математика с универсальным типом