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
如有错误请指正!
谢谢!
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
如有错误请指正!
谢谢!
相关文章推荐
- 在C语言的宏中使用类型关键字
- C语言中的static和extern关键字——【链接属性】和【存储类型】角度解析
- c语言中volatile关键字
- C语言中restrict关键字学习
- Objective-C语言--self和super关键字解析
- C语言中的far关键字
- C语言的inline关键字
- 关于C语言中关键字的使用
- C语言32个关键字
- C语言中的extern关键字用法
- C语言中的typeof关键字
- c语言typedef关键字的理解
- 陈正冲老师讲c语言之const关键字
- register---C语言中最快的关键字
- C语言链表操作(新增单向链表的逆序建立)
- [C] 让VC支持C99的整数类型V1.01。避免包含目录问题,更名auto_stdint.h、auto_inttypes.h(在VC6至VC2012、GCC、BCB等编译器下测试通过)
- c语言中restrict关键字的理解
- Daily-C-Study(14):C语言sizeof关键字
- C语言中static关键字的常见用法及举例
- <2012 9 30> 郝斌C语言课绪论 要点摘录