• _Generic关键字及其语法和应用(C11标准),C语言_Generic详解

    对接触过面向对象程序设计的程序员来讲,相信各位对泛型编程并不陌生。在 C11 标准中,_Generic 关键字可以让 C 语言也如同 C++ 等面向对象程序设计语言一样,使其支持轻量级的泛型编程设计。

    利用 _Generic 关键字,可以简单地将一组具有不同类型却有相同功能的函数抽象为一个统一的接口,语法形式如下:

    generic-selection:
        _Generic (assignment-expression, generic-assoc-list)
    generic-assoc-list:
        generic-association
        generic-assoc-list , generic-association
    generic-association:
        type-name : assignment-expression
        default : assignment-expression

    与 sizeof 与 typeof 类似,_Generic 中的 assignment-expression 只用于在编译时获得该表达式的类型,而不会对该表达式做运行时计算,如以下代码所示。

    #include <stdio.h>
    #include <string.h>
    #include <stddef.h>
    #include <stdint.h>
    #define getTypeName(x) _Generic((x), _Bool:"_Bool",\
        char: "char", \
        signed char: "signed char", \
        unsigned char: "unsigned char", \
        short int: "short int", \
        unsigned short int: "unsigned short int", \
        int: "int", \
        unsigned int: "unsigned int", \
        long int: "long int", \
        unsigned long int: "unsigned long int", \
        long long int: "long long int", \
        unsigned long long int: "unsigned long long int", \
        float: "float", \
        double: "double", \
        long double: "long double", \
        char *: "pointer to char", \
        void *: "pointer to void", \
        int *: "pointer to int")
    int main(void)
    {
        char c = 'a';
        size_t s;
        ptrdiff_t p;
        intmax_t i;
        int arr[3] = { 0 };
        printf("s is '%s'\n", getTypeName(s));
        printf("p is '%s'\n", getTypeName(p));
        printf("i is '%s'\n", getTypeName(i));
        printf("c is '%s'\n", getTypeName(c));
        printf("arr is '%s'\n", getTypeName(arr));
        printf("0x7FFFFFFF is '%s'\n", getTypeName(0x7FFFFFFF));
        printf("0xFFFFFFFF is '%s'\n", getTypeName(0xFFFFFFFF));
        printf("0x7FFFFFFFU is '%s'\n", getTypeName(0x7FFFFFFFU));
    }

    运行结果为:
    s is 'unsigned int'
    p is 'int'
    i is 'long long int'
    c is 'char'
    arr is 'pointer to int'
    0x7FFFFFFF is 'int'
    0xFFFFFFFF is 'unsigned int'
    0x7FFFFFFFU is 'unsigned int'

    除此之外,还必须保证 generic-association-list 中有与 assignment-expression 类型相同的 generic-association 与之对应,否则编译就会报错。例如,在上面代码的main函数中添加如下两行代码:

    float *fp=NULL;
    printf("fp is '%s'\n", getTypeName(fp));

    很显然,generic-assoc-list 中没有 generic-association 与 fp 相匹配的类型,从而导致编译出错,如图 1 所示。


    图 1 类型不匹配

更多...

加载中...