zoukankan      html  css  js  c++  java
  • 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)

    complex.h是C标准函数库中的头文件,提供了复数算术所需要的宏定义与函数声明。

    #define complex  _Complex
    #define _Complex_I  ((const float _Complex)__I__)
    #define I  _Complex_I

    C99规定了关键字_Complex。因而有3种复数类型:

    • double _Complex
    • float _Complex
    • long double _Complex

    次序不是必须遵守的,比如float _Complex也可以写成_Complex float。_Complex_I扩展为类型为const float _Complex的常量值,其值为虚数单位。C99规定complex作为宏扩展为_Complex。但C++未定义complex宏。gcc仅支持complex type,不支持imaginary type。因此宏I扩展为_Complex_I

    <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 + %fi
    ", creal(cmp), cimag(cmp));
        return 0;  
    }  

    2.指定初始化(Designated Initializers)

    在初始化结构体和数组时,可以通过指定具体成员名或数组下标来赋初值

    要指定数组的索引对应的值,可以在相应的元素值前使用‘[index] =’,index必须是常量表达式例如:

    int a[6] = { [4] = 29, [2] = 15 };

    等价于:

     int a[6] = { 0, 0, 15, 0, 29, 0 };

    还可以向下面这样初始化:

    int a[10] = { [1] = 1, [8 ... 9] = 10 };

    这样可以只初始化a[1], a[8], a[9]三个元素,其他元素的值为0,等价于:

    int a[10] = {0, 1, 0, 0, 0, 0, 0, 0, 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);
    }
    GNU示例代码

    也可以在结构体或是联合中使用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("%d
    ", 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)相比,具备以下优点:

    • 参数类型检查:宏定义中所使用的参数仅仅是在宏定义中被替换,不进行任何的类型检查
    • 返回值:宏定义中无法使用return返回
    • 便于调试

    示例代码:

    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, 'a', 0};
         structure = temp;
    }

    也可以创建一个数组:

    char **foo = (char *[]) { "x", "y", "z" };

    更多实例:

    static struct foo x = (struct foo) {1, 'a', 'b'};
    static int y[] = (int []) {1, 2, 3};
    static int z[] = (int [3]) {1};
    //等价于下面的代码:
    static struct foo x = {1, 'a', 'b'};
    static int y[] = {1, 2, 3};
    static int z[] = {1, 0, 0};

    10.for循环变量初始化(for loop intializers)

    C99引入了C++中的for循环变量初始化方式:

    for(int i = 0; i < 10; ++i) {
      ...;
    }

    除了写起来方便以外,循环变量的生存周期也被最小化了。这也顺便杜绝了那种把循环变量带到循环外头继续用的恶习

    11.C99新增头文件

    C89中标准的头文件:
      <assert.h>             定义宏assert()
      <ctype.h>              字符处理
      <errno.h>              错误报告
      <float.h>               定义与实现相关的浮点值勤
      <limits.h>              定义与实现相关的各种极限值
      <locale.h>              支持函数setlocale()
      <math.h>              数学函数库使用的各种定义
      <setjmp.h>           支持非局部跳转
      <signal.h>             定义信号值
      <stdarg.h>            支持可变长度的参数列表
      <stddef.h>            定义常用常数
      <stdio.h>              支持文件输入和输出
      <stdlib.h>             其他各种声明
      <string.h>             字符串函数
      <time.h>               支持系统时间函数

    C99新增的头文件
      <complex.h>          支持复杂算法
      <fenv.h>               给出对浮点状态标记和浮点环境的其他方面的访问
      <inttypes.h>          定义标准的、可移植的整型类型集合,也支持处理最大宽度整数的函数
      <iso646.h>            首先在此1995年第一次修订时引进,用于定义对应各种运算符的宏
      <stdbool.h>           支持布尔数据类型类型,定义宏bool,以便兼容于C++
      <stdint.h>             定义标准的、可移植的整型类型集合,该文件包含在<inttypes.h>中
      <tgmath.h>           定义一般类型的浮点宏
      <wchar.h>             首先在1995年第一次修订时引进,用于支持多字节和宽字节函数
      <wctype.h>           首先在1995年第一次修订时引进,用于支持多字节和宽字节分类函数

    注意:还有一些新特性未总结进来,待充分理解实践之后将陆续补充

    参考资料

    https://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html#C-Extensions

  • 相关阅读:
    docker 安装ELK
    关于centOS安装配置mysql5.6那点事
    关于centOS安装配置xampp那点事
    PowerDesigner16.5连接Oracle数据库生成E-R图
    Microsoft Visual Studio 中工具箱不显示DevExpress控件的解决办法
    Linux 基础命令
    oracle数据库表空间创建&导入&导出
    weblogic10.3.6漏洞修改方案
    oracle数据库表空间追加数据库文件方法
    转移博客
  • 原文地址:https://www.cnblogs.com/wuyudong/p/c99-new-feature.html
Copyright © 2011-2022 走看看