1 K&R C C90,C99的改进

1 K&R C C90,C99的改进  

 

 

C语言是C++的子集,C++是C语言的超集。C++是在C语言的基础上,添加了面向对象和泛型编程的功能后,扩展而成的。

 

1)起源

 

1970年,AT&T贝尔实验室的Ken Thompson和Dennis Ritchie等人在DEC公司的PDP-7小型机上开发出了Unix操作系统,Dennis Ritchie以B语言为基础,参考了Algol68,于1972年设计出了C语言。1973年他们用C语言重写了Unix,

 

 

 

2)K&R C

开始的很多年,C语言没有国际标准,只有一个事实标准K&R C。直到1989年和1990年,才分别推出了ANSI C和ISO C(C89或C90);1999年ISO又推出了第2版(C99)。

 

4)C89/C90标准

标准的指导原则是:

 

l 相信程序员;

 

l 不妨碍程序员做需要完成的事情;

 

l 让语言保持短小简单;

 

l 只提供一种方法来执行一种操作;

 

l 使程序运行速度快,即使不能保证其可移植性。(不追求定义的抽象统一,更优先考虑运行效率)

 

标准C对K&R C的主要改变是,增加了函数原型(prototype),强调对函数的输入参数进行严格的类型检查;并补充定义了C语言的标准函数库。

 

函数原型的类型检查是指:在编译时,对调用函数的实参和函数定义时的形参的类型是否一致,进行严格的检查。目的是减少程序纠错的难度(这类问题在运行时很难查出),同时保证运行的安全和稳定性(避免函数调用栈溢出)。

 

例如:

 

u K&R C:(过时的)

 

power(); // 函数的前向声明

 

power(x, n) // 函数定义

 

int x, n;

 

{

 

……

 

}

 

int p = power(3) * power(3.9, 5.4); // 使用(编译可通过,运行时产生逻辑错误)

 

u C89/C90:(推荐的)

 

int power(int x, int n); // 函数声明1(函数原型)

 

int power(int, int); // 函数声明2(函数原型)

 

int power(int x, int n) // 函数定义

 

{

 

……

 

}

 

int p = power(3) * power(3.9, 5.4); // 使用(编译不能通过,错误:第1个调用

 

// 的参数太少、警告:第2个调用的参数自动转换为(3, 5))

 

 

 

l C89/C90对K&R C的其它改变有:

 

n 删除了关键字:entry(条目/入口)

 

n 增加了关键字:const(常型变量)、enum(枚举类型)、signed(有符号的,例如signed char)、void(空/无,可用于函数返回值和形参、通用指针类型)、volatile(易变变量,防止编译器错误的优化)

 

n 传递结构:允许将结构本身作为参数传递给函数(原来只允许传地址)

 

n 函数原型:增加了函数原型(便于编译器进行类型检查)

 

n 增加了预处理指令:#elif(else if)、#error(错误,强制编译停止)、#line(修改当前行号和源文件名)、#pragma(附注/编译指令,编译器定义的与实现有关的指令)

 

n 定义了固有宏:__LINE__(当前行号)、__FILE__(源文件名)、__DATE__(当前系统日期)、__TIME__(当前系统时间)、__STDC__(标准C版时为1)

 

5)C99标准

(1)修订目标

C99保持了C语言的本质特性,C继续是一种短小、清晰和高效的语言。C99并没有增加新的本质特性,但是为了满足新的需要,也进行很多小的修订。

 

l C99主要的修订目标有三点:

 

n 支持国际化编程,引入了支持国际字符集Unicode的数据类型和库函数;

 

n 修正原有版本的明显缺点。如整数的移植方法,例如int8_t、int16_t、int32_t和int64_t等类型;

 

n 针对科学和工程的需要,改进计算的实用性。例如添加了复数类型和新数学函数。

 

(2)具体修改

l C99对C89/C90的具体修改有:

 

n 增加了C++的//注释风格:原来C语言之支持多行注释:/*……*/,C99现在也识别单行注释:// ……

 

n 增加了关键字:inline(内联函数)、restrict(限制)、_Bool(布尔类型)、_Complex(复数)、_Imaginary(虚数)

 

u 内联函数(inline):链接时不是进行函数调用而是嵌入函数体代码(可减少调用的时间开销,适用于要求运行速度快的小型函数)

 

u restrict:只能用于指针,表明该指针是数据对象的唯一且初始的方式(不是通过指针的赋值运算另外来得的),便于编译器进行代码优化。

 

附注:微软公司VC扩展的restrict,是让编译器限制别名(如用typedef定义的)的使用,必须类型名完全一致(只是类型等价还不够)时,类型检验才能通过

 

u _Bool:布尔类型,为整数类型,一般用1(或非0)表示真、用0表示假。如果包含了C99新增加的标准库头文件stdbool.h,则可以用bool来代替_Bool,并可使用true和false,从而与标准C++兼容

 

u 复数和虚数类型:

 

l 如果包含了C99新增加的标准库头文件complex.h后,就可以用complex来代替_Complex、用imaginary来代替_Imaginary

 

l 有三种复数和虚数类型:float _Complex、double _Complex、long double _Complex;float _Imaginary、double _Imaginary、long double _Imaginary

 

l 在C99内部,是用二元数组来实现复数的,第一个数组元素为实部、第二个数组元素为虚部

 

l 可以用实数和(定义在complex.h中的)I来初始化一个复变量。例如:

 

#include <complex.h>

 

double complex z = 6.0 – 8.5 * I, w = 3.0, u = 4.0 * I;

 

 

 

C99的关键字(Keywords)(共37个)

 

auto

enum

restrict

unsigned

 

break

extern

return

void

 

case

float

short

volatile

 

char

for

signed

while

 

const

goto

sizeof

_Bool

 

continue

if

static

_Complex

 

default

inline

struct

_Imaginary

 

do

int

switch

 

 

double

long

typedef

 

 

else

register

union

 

 

 

其中:黑色的为K&R C原有的关键字,绿色的为C90添加的关键字,红色的为C99新增的关键字。(C90删除了K&R C的关键字entry)

 

n 增加了数据类型:(unsigned) long long [int](64位整数)(对应的打印输出格式为%lld或%llu) 

n 定义了可移植整数类型:因为同一整数类型,在不同字长的计算机系统中,可能位数不一样,这给移植带来了问题。因此,C99在新增加的头文件inttypes.h中定义了已有整数类型的一些别名,便于程序移植。例如:int8_t、int16_t、int32_t、int64_t,uint8_t、uint16_t、uint32_t、uint64_t;intptr_t、uintptr_t。以及表示对应类型常量的方法,例如INT8_C(128)、INT32_C(1234)。

 

n 增加了预定义宏:C99新加了两个预定义宏:__STDC_HOS 

 

 

 

 作者: 202.106.46.*  2009-11-10 9:11    

 

--------------------------------------------------------------------------------

 

2 K&R C C90,C99的改进  

 TED__(是本机环境时为1,否则为0)和__STDC__VERSION__(=199901L时为C99,否则为C89/C90)

 

n 提供了一个预定义标识符:__func__,为一个代表函数名的字符串(该函数中包含有此标识符),该标识符具有函数作用域。(宏具有文件作用域)

 

n 增加了浮点常量的十六进制格式:p或P表示后跟二进制指数(的十进制值)。例如:0xa.1cp10 = (10 + 1/16 + 12/256) * 210 = 10352.0

 

n 增加了浮点数的十六进制打印格式符:%a或%A(代替十进制的%e或%E)、%La或%LA(代替十进制的%Le或%LE)

 

n 可指定初始化的条目:在对数组和结构进行初始化时,原来必须从头到尾顺序指定初值,最多只能省掉对尾部部分赋初值(未被初始化的条目全被置为0)。C99可以用[i] = v的方法,在花括号中为指定条目i赋初值v。例如:

 

int a[6] = {[5] = 123}; // 最后一个数组元素的初值为123,其余的值全为0

 

int days[12] = {31, 28, [4] = 31, 30, 31, [1] = 29}; // 则初值序列为31 29 0 0 

 

// 31 30 31 0 0 0 0 0

 

n 支持变长数组(VLA = Variable-Length array):原来的C语言(包括C++)要求数组定义中的大小必须是整数常量[表达式],而C99允许使用变量。例如:

 

#define SIZE 12

 

……

 

int m, n;

 

……

 

int a1[5], a2{SIZE}; // C89可以

 

float a3[n], a4[m][n]; // C89不允许,C99可以

 

注意:这里的变长,不是说数组的大小可以 

 

 

 

 

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值