C99标准的新特性
C语言标准的发展C语言的发展历史大致上分为4个阶段:Old Style C、C89、C99和C11. C89是最早的C语言规范,于1989年提出,1990年先由ANSI(美国国家标准委员会,American National Standards Institute)推出ANSI版本,后来被接纳为ISO国际标准(ISO/IEC9899:1990),因而有时也称为C90,最经典的C语言教材[K&R]就是基于这个版本的,C89是目前最广泛采用的C语言标准,大多数编译器都完全支持C89,C99(ISO/IEC9899:1999)是在1999年推出的,加入了许多新的特性,但目前仍没有得到广泛支持,在C99推出之后相当长的一段时间里,连gcc也没有完全实现C99的所有特性。2011年12月8号,ISO 发布了新的 C 语言的新标准——C11,之前被称为C1X,官方名称 ISO/IEC 9899:2011。 本文地址:http://www.cnblogs.com/archimedes/p/c99-new-feature.html,转载请注明源地址。 现在介绍一下C99相对于C89或者ANSI C的新特性: 1.复数(complex)
#define complex _Complex #define _Complex_I ((const float _Complex)__I__) #define I _Complex_I C99规定了关键字
次序不是必须遵守的,比如float _Complex也可以写成_Complex float。 <complex.h>里面还包含了不少支持复数的数学函数(c打头的就是): 1、ccos,csin,ctan,cacos,casin,catan:复数域内的三角函数,有对应的f和l版本。 2、ccosh,csinh,ctanh,cacosh,casinh,catanh:复数域内的双曲函数,有对应的f和l版本。 3、cexp,clog,cabs,cpow,csqrt:复数域内的指数、对数、绝对值、幂函数,有对应的f和l版本。 4、carg,cimag,creal,conj,cproj:获取象限角、虚数部分、实数部分、a=x及b=-y、Riemann球上的投影,有对应的f和l版本。 代码: #include<stdio.h> #include<complex.h> int main() { double complex cmp = 1.3 + 2.3*I; printf("%f + %fin",creal(cmp),cimag(cmp)); return 0; } 2.指定初始化(Designated Initializers)在初始化结构体和数组时,可以通过指定具体成员名或数组下标来赋初值 要指定数组的索引对应的值,可以在相应的元素值前使用‘[index] =’,index必须是常量表达式例如: int a[6] = { [4] = 29,[2] = 15 }; 等价于: int a[6] = { 0,15,29,0 }; 还可以向下面这样初始化: int a[10] = { [1] = 1,[8 ... 9] = 10 }; 这样可以只初始化a[1],a[8],a[9]三个元素,其他元素的值为0,等价于: int a[10] = {0,1,10,10}; 对于结构体,指定成员名初始化可以使用‘.fieldname=’,例如: struct point { int x,y; }; 接下来初始化: struct point p = { .y = yvalue,.x = xvalue }; // 等价于 struct point p = { xvalue,yvalue }; 还可以使用冒号: struct point p = { y: yvalue,x: xvalue }; 当然也可以用在union中: union foo { int i; double d; }; union foo f = { .d = 4 }; 3.变长数组(Variable Length Arrays)C99允许可以定义一个长度为变量的数组(这个数组的长度可以到运行时才决定) FILE * concat_fopen (char *s1,char *s2,char *mode) { char str[strlen (s1) + strlen (s2) + 1]; strcpy (str,s1); strcat (str,s2); return fopen (str,mode); } 也可以在结构体或是联合中使用VLA: void foo (int n) { struct S { int x[n]; }; } 你可以使用alloca函数实现类似的功能,但是alloca函数并不是都实现,从另一角度而言,VLA更加的优秀 也可以使用VLA作函数参数: struct entry tester (int len,char data[len][len]) { /* ... */ } 当然也可以后传len struct entry tester (int len; char data[len][len],int len) //注意分号 { /* ... */ } 示例代码: #include<stdio.h> void func(int n) { int vla[n]; printf("%dn",sizeof(vla)); } int main() { func(4); return 0; } 4.单行注释
gcc支持像C++风格的注释,以‘//’开头直到一行的结束,很多其他支持C99的C编译器都支持,但是c99之前的版本有可能不支持 5.柔性数组成员(Flexible Array Members)?参见《C语言柔性数组》一文 6.long long类型C99支持64位整型,使用long long int 或使用unsigned long long int,将整型常量声明为long long int,在整数的后面加上‘LL’,若为unsigned long long int,则加上‘ULL’ 7.inline函数c/c++中的inline,使用在函数声明处,表示程序员请求编译器在此函数的被调用处将此函数实现插入,而不是像普通函数那样生成调用代码(申请是否有效取决于编译器)。一般地说,这样作的优点是省掉了调用函数的开销;缺点则是可能会增加代所生成目标代码的尺寸 实际上,即使没有手工指定inline函数,编译器一般还会选择一些代码量较小但使用频繁的函数作为inline函数,以此作为性能优化的途径之一。 和带参宏定义(Parameterized Macro)相比,具备以下优点:
示例代码: static inline int inc (int *a) { return (*a)++; } 8.bool类型记得以前都是自己写#define TRUE 1,#define FALSE ?0 或者 enum boolean之类的宏,现在可以使用<stdbool.h>的bool类型啦 9.复合常量(Compound Literals)简单来说复合常量就是允许你定义一个匿名的结构体或数组变量。如: struct foo {int a; char b[2];} structure; structure = ((struct foo) {x + y,‘a‘,0}); 等价于: { struct foo temp = {x + y,0}; structure = temp; } 也可以创建一个数组: char **foo = (char *[]) { "x","y","z" }; 更多实例: static struct foo x = (struct foo) {1,‘b‘}; static int y[] = (int []) {1,2,3}; static int z[] = (int [3]) {1}; //等价于下面的代码: static struct foo x = {1,‘b‘}; static int y[] = {1,3}; static int z[] = {1,0}; 10.for循环变量初始化(for loop intializers)C99引入了C++中的for循环变量初始化方式: for(int i = 0; i < 10; ++i) { ...; } 除了写起来方便以外,循环变量的生存周期也被最小化了。这也顺便杜绝了那种把循环变量带到循环外头继续用的恶习 11.C99新增头文件C89中标准的头文件: C99新增的头文件 注意:还有一些新特性未总结进来,待充分理解实践之后将陆续补充 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |