C11标准的泛型机制

 

Apple LLVM4.0已经支持了C11标准中的关键特性——泛型机制。尽管C11中的泛型机制比起C++的来要显得简陋不少,但是在做库的时候仍然十分管用。

下面我们就来看一下C11标准中的泛型表达式。


C11中的泛型机制由关键字_Generic引出,其语法形式为:

_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 


下面给出C代码例子:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#define GENERAL_ABS(x)  _Generic((x), int:abs, float:fabsf, double:fabs)(x)
 
static void GenericTest( void )
{
     printf ( "int abs: %d\n" , GENERAL_ABS(-12));
     printf ( "float abs: %f\n" , GENERAL_ABS(-12.04f));
     printf ( "double abs: %f\n" , GENERAL_ABS(-13.09876));
     
     int a = 10;
     int b = 0, c = 0;
     
     _Generic(a + 0.1f, int :b, float :c, default :b)++;
     printf ( "b = %d, c = %d\n" , b, c);
     
     _Generic(a += 1.1f, int :b, float :c, default :b)++;
     printf ( "a = %d, b = %d, c = %d\n" , a, b, c);
}


这边要注意的是,_Generic里的assignment-expression只获取其类型而不会对它做运行时计算。也就是说,编译器仅仅在编译时获得该表达式的类型,而不会产生任何其它指令。这个跟sizeof()、typeof(),以及C++中的typeid()和decltype()一样。

另外,generic-association-list中必须要有与assignment-expression类型相同的generic-association,否则编译会报错。当然,如果在generic-association-list中含有default处理,那么编译能顺利进行。如以下代码所示:

?
1
2
3
4
5
6
7
struct MyStruct { int a, b; } s;
_Generic( "Hello" , const char *: puts ( "OK!" ));    // ERROR! "Hello"为char[6]类型
_Generic( "Hello" , char [6]: puts ( "OK!" ));    // OK
_Generic(( const char *) "Hello" , const char *: puts ( "OK!" ));    // OK
_Generic(s, int : puts ( "OK!" ));    // ERROR
_Generic(s, struct MyStruct: puts ( "OK!" ));    // OK
_Generic(s, int : puts ( "Yep!" ), default : puts ( "Others" ));    // OK
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值