全部博文(26)
分类: C/C++
2009-03-05 20:18:51
C,是一种通用的,它主要用来进行。具有高效、灵活、功能丰富、表达力强和好等的特点,在程序员中备受青睐。
C语言是由的研制者(Dennis Ritchie)和(Ken Thompson)于1970年研制出的的基础上发展和完善起来的。C语言可以广泛应用于不同的,例如、、及等。C语言是一种,同时具有和的优点。在C语言的基础上发展起来的有支持多种的语言,网络上广泛使用的、,微软的等。
,(ANSI) 对C语言进行了标准化,于1983年颁布了第一个C语言标准草案(83 ANSI C),后来于1987年又颁布了另一个C语言标准草案(87 ANSI C)。最新的C语言标准是在1999年颁布并在2000年3月被ANSI采用的 C99 ,但由于未得到主流编译器厂家的支持,直到C99 并未被广泛使用,增加了若干新特性后 C99 已经逐渐让C语言和分道扬镳。
目录[] |
C语言的主要不足是缺乏对真实事物的描述手段。用C语言表达复杂的将 会十分困难,而且代码量也明显高于C++语言。同时C语言过度的信赖程序员的做法也一直存在很大争议,是否允许程序员随意修改内存中的任何东西一直都是争 论的焦点所在。C语言的不足可以由C语言发展而来的新的编程语言所改进。Cyclone语言拥有提防内存错误的特性。C++和Objective C提供了用于的编程结构。和在提供面向对象编程结构的同时,也提供了垃圾收集机制,这使得对内存的管理更加透明与自动化。
但是並不是所有的這些特性都是有效的。例如,預處理通常作為一個獨立的程式被處理,這使得預處理的程式並不一定被完全編譯。
雖然C是高階語言,但是它同時擁有一些組合語言的特性,對其他的語言來說這是接近低階語言的特點。例如,在C語言裏,程式師可以對電腦記憶 體進行管理。在默認的情況下,C語言不會對陣列的範圍進行檢查,也就是說即使陣列越界,C語言也不會作出錯誤提示。對電腦記憶體的管理使得程式員可以編出 更快捷、更有效的程式,這對於設備驅動程式來說尤為重要。但是這也使得程式容易產生令人討厭的「」,例如緩衝器溢出錯誤。然而,這些錯誤可以由一些工具來避免。
C語言的不足可以由從C語言發展而來的更新的編程語言改進。Cyclone語言的擁有提防對於記憶體錯誤的特性。C++和Objective C提供了用於面向物件的編程結構。Java和C#增加了面向物件的結構使得對記憶體的管理自動化。
C語言的第一次發展在1969年到1973年之間。C之所以被稱為C是因為C語言的很多特性是由一種更早的被稱為B語言的編程語言中發展而來的。
到了1973年,C語言已經可以用來編寫Unix操作系統的內核。這是第一次用C語言來編寫操作系統的內核。丹尼斯·裡奇和Brian Kernighan在1978年出版了《C程序設計語言》(The C Programming Language,經常簡稱為「白皮書」或「K&R」)。
1980年以後,使得C變得更為廣泛的流行,使得C一度成為了操作系統和應用程序編程的首選。甚至到今天,它仍被廣泛用於編寫操作系統以及作為廣泛的計算機教育的語言。2005年4月,C++之父稱C++用戶超過300萬。
1980年代晚期,和為C語言添加了面向對象的特性.這種語言成為了。C++現在廣泛應用的在下運行的商業應用程序的編制,然而C仍然是的熱門編程語言。
C不断的从它的第一版本进行改进。在1978年,和里奇的《C程序设计语言》第一版出版。它介绍了下面的有关C语言版本的特性:
在以后的几年里,《C程序设计语言》一直被广泛作为C语言事实上的规范。在这本书中,C语言通常被表述成“K&R C”。(第二版的包括了ANSI C标准)
K&R C通常被作为C编译器所支持的最基本的C语言部分。虽然现在的编译器并不一定都完全遵循ANSI标准,但K&R C作为C语言的最低要求仍然要编程人员掌握。但是无论怎样,现在使用广泛的C语言版本都已经与K&R C相距甚远了,因为这些编译器都使用ANSI C标准。 //....
1989年,C语言被ANSI标准化。(ANSI X3.159-1989)。标准化的一个目的是扩展K&R C。这个标准包括了一些新的特性。在K&R出版后,一些新的特征被“非官方”的加到C语言中。
在ANSI标准化自己的过程中,一些新的特征被加了进去。ANSI也规定了一套标准函数库。ANSI ()成立 ISO/IEC JTC1/SC22/WG14工作组来规定国际标准的C语言。通过对ANSI标准的少量修改,最终通过了ISO 9899:1990。随后ISO标准被ANSI采纳。
传统C语言到ANSI/ISO标准C语言的改进包括:
作为对标准的维护与更新,WG14工作小组在对1985年颁布的标准做了两处技术修订(缺陷修复)和一个补充(扩展)。下面是1995年做出的所有修改:
在ANSI标准化后,WG14小组继续致力于改进C语言。新的标准很快推出,就是ISO9899:1999(出版)。这个版本就是通常提及的C99。它被ANSI于三月采用。
在C99中包括的特性有:
struct {int a[3], b;} hehe[] = { [0].a = {1}, [1].a = 2 };
struct {int a, b, c, d;} hehe = { .a = 1, .c = 3, 4, .b = 5} // 3,4 是对 .c,.d 赋值的
但是各个公司对C99的支持所表现出来的兴趣不同。当GCC和其它一些商业编译器支持C99的大部分特性的时候,和却似乎对此不感兴趣。
下面是一个在标准输出设备上输出的简单程序,这种程序通常作为开始学习编程语言时的第一个程序:
#include
int main(void)
{
printf("Hello, world!\n");
return 0;
}
C语言由函数和变量组成。C的函数就像是中的子程序和函数。
在C语言中,程序从main开始执行。main函数通过调用和控制其他函数进行工作。例如上面的printf。程序员可以自己写函数,或从库中调用函数。在上面的return 0;使得main返回一个值给调用程序的外壳,表明程序已经成功运行。
一个C语言的函数由返回值、函数名、参数列表(或void表示没有返回值)和函数体组成。函数体的语法和其它的复合的语句部分是一样的。
C语言中的复合语句(或称语句块)的格式为:
{语句;语句;……}
复合语句可以使得几个语句变成一个语句。
但一般情况下,我们不推荐这样多个语句顺序书写, 因为这样会使其可读性减弱,加大代码维护难度。
C语言有三种条件语句形式。两种是if,另一种是switch。
两种if包括:
if (条件表达式)
语句;
以及
if (条件表达式)
语句;
else
语句;
在条件表达式中,任何非零的值表示条件为真;如果条件不满足,程序将跳过if后面的语句,直接执行if后面的语句。但是如果if后面有else,则当条件不成立时,程序跳到else处执行。
switch通常用于对几种有明确值的条件进行控制。它要求的条件值通常是整数或字符。与switch搭配的条件转移是case。使用case后面的标值,控制程序将跳到满足条件的case处一直往下执行,直到语句结束或遇到break。通常可以使用default把其它例外的情况包含进去。如果switch语句中的条件不成立,控制程序将跳到default处执行。switch是可以嵌套的。
switch (<表达式>) {
case <值1> :
<语句>
case <值2> :
<语句>
default :
<语句>
}
C语言有三种形式的循环语句:
do
<语句>
while (<表达式>);
while (<表达式>)
<语句>;
for (<表达式1> ; <表达式2> ; <表达式3>)
<语句>;
在while和do中,语句将执行到表达式的值为零时结束。在do...while语句中,循环体将至少被执行一次。这三种循环结构可以互相转化:
for (e1; e2; e3)
s;
相当于
e1;
while (e2) {
s;
e3;
}
当循环条件一直为真时,将产生死循环。
跳转语句包括四种:goto,continue,break和return。
goto语句是无条件转移语句:
goto 标记
标记必须在当前函数中定义,使用“标记:”的格式定义。程序将跳到标记处继续执行。由于goto容易产生阅读上的困难,所以应该尽量少用。
continue语句用在循环语句中,作用是结束当前一轮的循环,马上开始下一轮循环。
break语句用在循环语句或switch中,作用是结束当前循环,跳到循环体外继续执行。但是使用break只能跳出一层循环。在要跳出多重循环时,可以使用goto使得程序更为简洁。
当一个函数执行结束后要返回一个值时,使用return。return可以跟一个表达式或变量。如果return后面没有值,将执行不返回值。
() [] -> . ! ++ -- (cast) | 括号、成员、逻辑非、自加、自减、强制转换 |
++ -- * & ~ ! + - sizeof | 单目运算符 |
* / % | 算术运算符 |
算术运算符 | |
<< >> | 位运算符 |
< <= > >= | 关系运算符 |
== != | 关系运算符号 |
& | 位与 |
^ | 位异或 |
| | 位或 |
&& | 逻辑与 |
|| | 逻辑或 |
?: | 条件运算符 |
= += -= *= /= %= <<= >>= &= |= ^= | 赋值运算符 |
, | 顺序运算符 |
注意:以下是典型的数据位长和范围。但是编译器可能使用不同的数据位长和范围。这取决于使用的编译器。请参考具体的参考手册。
在头文件
关键字 | 位长 | 范围 |
char |
1 | -128..127 or 0..255 |
unsigned char |
1 | 0..255 |
signed char |
1 | -128..127 |
int |
2 or 4 | -32768..32767 or -2147483648..2147483647 |
short int |
2 | -32768..32767 |
long int |
4 | -2147483648..2147483647 |
float |
4 | 3.4x10-38E..3.4x10+38E |
double |
8 | 1.7x10-308E..1.7x10+308E |
long double |
12 | ??? |
如果一个变量名后面跟着一个有数字的中括号,这个声明就是数组声明。字符串也是一种数组。它们以ASCII的NUL作为数组的结束。
例如:
上面最后一个例子创建了一个数组,但也可以把它看成是一个多维数组。注意数组的下标从0开始。这个数组的结构如下:
a[0][0] |
a[0][1] |
a[0][2] |
a[0][3] |
a[1][0] |
a[1][1] |
a[1][2] |
a[1][3] |
a[2][0] |
a[2][1] |
a[2][2] |
a[2][3] |
例子(*)创建了一个3*3的二维数组,初始化时有些元素并未赋值.如下:
为0的位置的数值是随机的.
如果一个变量声明时在前面使用*号,表明这个变量是一个指针。换句话说,该变量是一个地址,而*则是取内容操作符,意思是取这个内存地址里存储的内 容。指针是C语言区别于其他同时代高级语言的主要特征之一。指针是一把双刃剑,许多操作可以通过指针自然的表达,但是不正确的或者过分的使用指针又会给程 序带来大量潜在的错误。
例如:
储存在指针中的地址所指向的数值在程序中可以由*读取。例如,在第一个例子中,*pi是一个整型数据。这叫做引用一个指针。
另一个运算符&,叫做取地址运算符,它将返回一个变量、数组或函数的存储地址。因此,下面的例子:
i和*pi在程序中可以相互交替使用,直到pi被改变成指向另一个变量的指针。
要使用字符串并不需要引用库,但是C标准库确实包含了一些用于对字符串进行操作的函数,使得它们看起来就像字符串而不是数组。使用这些函数需要引用
在C语言中,输入和输出是经由标准库中的一组函数来实现的。在ANSI/ISO C中,这些函数被定义在头文件
有三个标准输入/输出是预定义的:
这些定义在运行过程中是自动的打开和关闭的,所以它们并不需要进行显式定义。
下面的这个例子显示了一个过滤程序(filter program)是怎样构成的。
#include
int main(){
int c;
while (( c = getchar()) != EOF ) {
if (anErrorOccurs) {
fputs("an error eee occurred\n", stderr);
break;
}
putchar(c);
}
}
在命令行赋予程序的参数将通过在main()函数中定义一个整型参数(int)和一个指向字符指针的指针型参数(char **)来实现,前者传递命令行参数的个数,后者传递命令行参数内容。习惯上将这两个参数分别命名为argc和argv。程序文件名被作为第一个命令行参数。
对于下列程序:
#include
int main(int argc, char **argv) {
int i;
for(i=0;iprintf("%d:%s\n",i,argv[i]);
return 0;
}
输入命令(假设该程序生成C:\TC\a.exe): a one two three
则会得到下面的输出结果:
0:C:\TC\A.EXE
1:one
2:two
3:three
以下列出由C语言提供的标准函数库,函数库通过#include进行引用。
在C89标准中:
在95年的修正版中
在C99中增加了六个函数库
char | short | int | unsigned |
long | float | double | struct |
union | void | enum | signed |
const | volatile | typedef | auto |
register | static | extern | break |
case | continue | default | do |
else | for | goto | if |
return | switch | while | sizeof |