05.C语言进阶——泛型实现

C语言之泛型实现

原文参考《C语言实现泛型 C11关键字_Generic

C语言本身不支持真正意义上的泛型编程,但是却在一定程度上可以“实现泛型编程”,借助于宏展开功能(#define)和类型重定义(typedef)实现轻量级的泛型编程,随着C11标准的发布, 由_Generic关键字可以支持泛型编程(C++不支持该关键字)那么_Generic语法格式:

_Generic ( assignment-expression , generic-assoc-list )
// 详细释义:
// assignment-expression:赋值表达式,可以认为是变量var
// generic-assoc-list:泛型关联表,其语法为:
type-name : expression, type-name : expression, ..., default : expression
// eg:
_Generic((var), type1 : ..., type2 : ..., ……, default : ...) 

简述为:

_Generic (赋值表达式,泛型关联表 )
1. default不是必须的
2. generic-assoc-list中的expression仅仅是普通的宏替换

演示案例1:类型自动匹配

运行结果:

附源码展示:

#include<stdio.h>
#define GET_TYPENAME(var) _Generic((var), \
    int:"int",\
    char:"char", \
    float:"float", \
    double:"double", \
    char *:"char *",   \
    default: "other type")

#define GET_FORMAT(signal) _Generic((signal),\
                                    int:"%d\n", \
                                    char:"%c\n", \
                                    char *:"%s\n",\
                                    default:"%f\n")

int main(int argc, char** argv ) {
    int x1;
    int* x2;
    char x3[20] = "hello world!";
    x1 = 666666;
    
    // 范例1
    printf(GET_FORMAT(x1), x1);
    printf(GET_FORMAT(x3), x3);

    // 范例2
    printf("type: x1 = %s\n", GET_TYPENAME(x1));
    printf("type: x2 = %s\n", GET_TYPENAME(x2));
    printf("type: x3 = %s\n", GET_TYPENAME(x3));

    // 范例3
    // 泛型中的值会不会发生改变?
    // 答案:不会
    int k = 1;
    GET_TYPENAME(k++);
    GET_TYPENAME(++k);
    GET_TYPENAME(k*=2);
    GET_TYPENAME(k=4);
    printf("k = %d\n", k);
    return 0;
}

演示案例2:重载函数

运行结果1:

运行结果2:

附源码展示:

#include<stdio.h>
// 重载函数实现
int add_int(int a, int b) {
    printf("%d + %d = %d\n", a, b, a + b);
    return a + b;
}
float add_float(float a, float b) {
    printf("%f + %f = %f\n", a, b, a + b);
    return a + b;
}
void nofind(void) {
    printf("no find typed for the function!");
}
// 方式1
// 重载宏
#define ADD(x, y) _Generic((x), \
                    int: add_int(x, y), \
                    float: add_float(x, y), \
                    default: nofind())

// 方式2
// 重载宏
#define PLUS(x, y) _Generic((x), \
                    int: add_int, \
                    float: add_float, \
                    default: nofind) (x, y)

/*
int main(int argc, char** argv) {
    // 范例1
    ADD(1, 3);
    ADD(1.1f, 1.3f);
    ADD(1, 1.1);    // 数值1.1被解释int类型处理 
    
    // 范例2
    PLUS(1, 3);
    PLUS(1.1f, 1.3f);
    PLUS(1, 1.1);
    return 0;
}
*/

// Clang泛型中_Generic的语句中,++ 、*=、 = 等操作都不会让变量发生改变 
// 来看另一段代码,来自百度百科对C11中_Generic关键字的例程。
int main(int argc, char** argv) {
    int a = 10;
    int b = 0, c = 0;
    _Generic(a + 0.1f, int:b, float:c, default:b)++;
    printf("a = %d, b = %d, c = %d\n", a, b, c);
    
    _Generic(a += 1.1f,int:b, float:c, default:b)++;
    printf("a = %d, b = %d, c = %d\n", a, b, c);
    return 0;
}
posted @ 2021-07-31 16:01  skyuz  阅读(2882)  评论(0编辑  收藏  举报