您的位置:首页 > 编程语言 > C语言/C++

C语言 C99新增关键字 2012

2014-03-30 15:29 302 查看
在ANSI的标准确立後,C语言的规范在一段时间内没有大的变动,然而C++在自己的标准化建立过程中继续发展壮大。《标准修正案一》在1994年为C语言建立了一个新标准,但是只修正了一些C89标准中的细节和增加更多更广的国际字符集支持。不过,这个标准引出了1999年ISO
9899:1999的发表。它通常被称为C99。C99被ANSI于2000年3月采用。

在C99中包括的特性有:

1.增加了对编译器的限制,比如源程序每行要求至少支持到 4095 字节,变量名函数名的要求支持到 63 字节(extern 要求支持到 31)。
2.增强了预处理功能。例如:
a.巨集支持取可变参数 #define Macro(...) __VA_ARGS__
b.使用巨集的时候,允许省略参数,被省略的参数会被扩展成空串。
c.支持 // 开头的单行注释(这个特性实际上在C89的很多编译器上已经被支持了)
3.增加了新关键字 restrict, inline, _Complex, _Imaginary, _Bool支持 long long, long double
_Complex, float _Complex 等类型
4.支持不定长的数组,即数组长度可以在运行时决定,比如利用变量作为数组长度。声明时使用 int a[var] 的形式。不过考虑到效率和实现,不定长数组不能用在全局,或
struct与 union 里。
5.变量声明不必放在语句块的开头,for 语句提倡写成 for(int i=0;i<100;++i) 的形式,即i 只在 for
语句块内部有效。
6.允许采用(type_name){xx,xx,xx} 类似于 C++ 的构造函数的形式构造匿名的结构体。
7.初始化结构的时候允许对特定的元素赋值,形式为:

struct {int a[3],b;} foo[]
= {
[0].a
= {1},
[1].a
= 2 };

struct {int a, b, c, d;}
foo = {
.a = 1,
.c = 3, 4,
.b = 5}
// 3,4 是对
.c,.d 赋值的

8.格式化字符串中,利用 \u 支持 unicode 的字符。
9.支持 16 进制的浮点数的描述。
10.printf scanf 的格式化串增加了对 long long int 类型的支持。
11.浮点数的内部数据描述支持了新标准,可以使用 #pragma 编译器指令指定。
12.除了已有的 __line__ __file__ 以外,增加了 __func__ 得到当前的函数名。
13.允许编译器化简非常数的表达式。
14.修改了 / % 处理负数时的定义,这样可以给出明确的结果,例如在C89中-22 / 7 = -3, -22 % 7 = -1,也可以-22
/ 7= -4, -22 % 7 = 6。 而C99中明确为 -22 / 7 = -3, -22 % 7 = -1,只有一种结果。
15.取消了函数返回类型默认为 int 的规定。
16.允许 struct 定义的最后一个数组不指定其长度,写做 [] 。
17.const const int i 将被当作 const int i 处理。
18.增加和修改了一些标准头文件,比如定义 bool 的 <stdbool.h> ,定义一些标准长度的 int 的
<inttypes.h> ,定义复数的 <complex.h> ,定义宽字符的 <wctype.h> ,类似于泛型的数学函数
<tgmath.h>, 浮点数相关的 <fenv.h>。 在<stdarg.h> 增加了 va_copy 用于复制 ... 的参数。<time.h>
里增加了 struct tmx ,对 struct tm 做了扩展。
19.输入输出对宽字符以及长整数等做了相应的支持。

但是各个公司对C99的支持所表现出来的兴趣不同。当GCC和其它一些商业编译器支持C99的大部分特性的时候,微软和Borland却似乎对此不感兴趣。

在C99中新增了5个关键字:
_Bool:布尔类型,用来表示假,零表示假,非零表示真。所有非零的数赋值给布尔型变量,最终的值还是1。


_Bool b1, b2;

b1 = 99;

b2 = -99;

打印b1, b2的值都将为1(true)。
包含stdbool.h后,可以直接用bool代替_Bool,同时也可以使用true和false表示真和假。
stdbool.h内容如下:

#ifndef _STDBOOL_H

  #define _STDBOOL_H

  #ifndef __cplusplus

  #define bool _Bool

  #define true 1

  #define false 0

  #else /* __cplusplus
*/

  /* Supporting
in C++
is a GCC extension.
*/

  #define _Bool bool

  #define bool bool

  #define false
false

  #define true
true

  #endif /* __cplusplus
*/

  /* Signal that all the definitions are present.
*/

  #define __bool_true_false_are_defined 1

  #endif /* stdbool.h
*/

_Complex, _Imaginary:复数类型和虚数类型,C99提供了三种复数类型和虚数类型:float
_Complex,double _Complex,long double _Complex和float _Imaginary,double _Imaginary,以及 long double _Imaginary。复数类型包括一个实部和一个虚部,虚数类型没有实部,只有虚部。
例:

#include <complex.h>

double _Complex x = 5.2;
/* 实部等于 5.2,虚部为 0
*/

double _Complex y = 5.0
* i;
/* 实部为 0,虚部为 5.0
*/

double _Complex z = 5.2 – 5.0
* i;
/* 实部为 5.2,虚部为 5.0
*/

同样在程序中包含complex.h后,可以用 complex来代表 _Complex,用imaginary来代表 _Imaginary,以及用 I来代表虚数单位 i,也就是 -1的平方根。
complex.h内容如下

#ifndef _COMPLEX_H

#define _COMPLEX_H 1

#include <features.h>

/*
Get general and ISO C99 specific information.
*/

#include <bits/mathdef.h>

__BEGIN_DECLS

/* We might need
to add support for more compilers here. But since ISO

C99 is out hopefully all maintained compilers will soon provide the data

types `float complex'
and `double complex'.
*/

#if __GNUC_PREREQ
(2, 7)
&&
!__GNUC_PREREQ (2, 97)

# define _Complex __complex__

#endif

#define complex _Complex

/* Narrowest imaginary unit. This depends
on the floating-point

evaluation method.

XXX This probably has to go into a gcc related file.
*/

#define _Complex_I (__extension__ 1.0iF)

/* Another more descriptive name
is `I'.

XXX Once we have the imaginary support switch this
to _Imaginary_I.
*/

#undef I

#define I _Complex_I

/* The file
<bits/cmathcalls.h> contains the prototypes
for all the

actual math functions. These macros are used
for those prototypes,

so we can easily declare each
function as both `name'
and `__name',

and can declare the float versions `namef'
and `__namef'.
*/

#define __MATHCALL(function, args)
\

__MATHDECL (_Mdouble_complex_,function, args)

#define __MATHDECL(type,
function, args)
\

__MATHDECL_1(type,
function, args);
\

__MATHDECL_1(type, __CONCAT(__,function),
args)

#define __MATHDECL_1(type,
function, args)
\

extern type __MATH_PRECNAME(function) args __THROW

#define _Mdouble_ double

#define __MATH_PRECNAME(name) name

#include <bits/cmathcalls.h>

#undef _Mdouble_

#undef __MATH_PRECNAME

/*
Now the float versions.
*/

#ifndef _Mfloat_

# define _Mfloat_ float

#endif

#define _Mdouble_ _Mfloat_

#ifdef __STDC__

# define __MATH_PRECNAME(name) name##f

#else

# define __MATH_PRECNAME(name) name/**/f

#endif

#include <bits/cmathcalls.h>

#undef _Mdouble_

#undef __MATH_PRECNAME

/*
And the long double versions. It
is non-critical
to define them

here unconditionally since `long double'
is required in ISO C99.
*/

#if (__STDC__
- 0 || __GNUC__
- 0)
\

&&
(!defined __NO_LONG_DOUBLE_MATH
\

|| defined __LDBL_COMPAT
\

||
!defined _LIBC)

# if defined __LDBL_COMPAT
|| defined __NO_LONG_DOUBLE_MATH

# undef __MATHDECL_1

# define __MATHDECL_1(type,
function, args)
\

extern type __REDIRECT_NTH(__MATH_PRECNAME(function), args,
function)

# endif

# ifndef _Mlong_double_

# define _Mlong_double_ long double

# endif

# define _Mdouble_ _Mlong_double_

# ifdef __STDC__

# define __MATH_PRECNAME(name) name##l

# else

# define __MATH_PRECNAME(name) name/**/l

# endif

# include <bits/cmathcalls.h>

#endif

#undef _Mdouble_

#undef __MATH_PRECNAME

#undef __MATHDECL_1

#undef __MATHDECL

#undef __MATHCALL

__END_DECLS

restrict:用来限定指针,表明指针是访问一个数据对象的唯一且初始化对象。作用是告诉编译器除了该指针,其他任何指针都不能对所指向的数据进行存取,以便编译器优化代码。
详细讲解参考:http://bigwhite.blogbus.com/logs/174915680.html
inline:内联函数,是为了解决C 预处理器宏存在的问题所提出一种解决方案,用来提高函数使用效率。内联函数使用inline关键字定义,并且函数体和申明必须结合在一起, 否则编译器将他作为普通函数对待。

inline int function(int n);

inline int function(int n)

{

return ((n%2)?1:0);

}

内联函数把代码也加放入了符号列表中,避免了频繁调用函数对栈带来的消耗,达到优化代码的作用。所以内联函数本身不能太复杂。GCC对inline做了自己的扩展。
详见:/article/7052248.html

参考资料:
维基百科.C语言
http://zh.wikipedia.org/wiki/C%E8%AF%AD%E8%A8%80
关于C语言中的Complex(复数类型)和imaginary(虚数类型)
http://zxlruby.blog.163.com/blog/static/22583152201092994324459/

也谈C语言的restrict类型修饰符
http://bigwhite.blogbus.com/logs/174915680.html

C语言inline详细讲解
/article/7052248.html

理解内联函数inline在C中的使用
http://www.abc188.com/info/html/chengxusheji/C-C--/20080224/9676.html

如有错误请指正!
谢谢!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: