C语言发展史
C语言诞生
1972年,贝尔实验室的丹尼斯·里奇(Dennis Ritch)和肯·汤普逊(Ken Thompson)在开发UNIX操作系统时,在B语言的基础上设计了C语言。
K&R C / 经典C
1987年,布莱恩·柯林汉(Brian Kernighan)和丹尼斯·里奇(Dennis Ritch)合著的The C Programming Language(《C语言程序设计》)第1版是公认的C标准,通常称为“K&R C”或 “经典C”。
ANSI C / C89 / ISO C / C90
1983年美国国家标准协会(ANSI)组建了一个委员会(X3J11),X3J11开发了一套新的C标准,并于1989年正式公布(称为ANSI C或C89)。ANSI C标准定义了C语言和C标准库。国际标准化组织(ISO)于1990年采用了这套C标准(称为ISO C或C90),ISO C和ANSI C是完全相同的标准。由于ANSI先公布C标准,因此业界人士通常使用ANSI C。
C99
1994年,ANSI/ISO联合委员会(C9X委员会)开始修订C标准,最终发布了C99标准。
C11
C语言标准委员会在2011发布了C11标准。
第一个C语言程序
GNU是GNU’s Not Unix!的递归缩写。GNU项目始于1987年,主要目标是开发GNU操作系统。虽然GNU自己的内核 Hurd 仍在开发中,但已经开发出了大量的软件。GCC(GNU Compiler Collection,GNU编译器集合)是该项目的产品之一。gcc原本作为GNU操作系统的官方编译器,现已被大多数类Unix操作系统(如Linux、BSD、Mac OS X等)采纳为标准的编译器,gcc同样适用于微软的Windows。gcc最初用于编译C语言,随着项目的发展gcc已经成为了能够编译C、C++、Java、Ada、fortran、Object C、Object C++、Go语言的编译器大家族。
与Linux系列操作系统不同,Windows原生环境不提供类似gcc,Clang的C/C++语言源程序编译运行工具链。运行在Windows上的IDE(集成开发环境),比如CodeBlocks之类,一般都使用MinGW配置模拟Linux下的开发环境来进行Windows下的开发。使用Codeblocks自带的MinGW配置环境变量:
C代码编译成可执行程序经过4步:
- 预处理:编译之前进行,这一步并不会检查语法。生成预处理文件(.i 文件)。
- 预处理:gcc -E hello.c -o hello.i ,“-o hello.i” 指定输出文件的名字为hello.i 。
- 处理所有的注释,以空格代替。
- 将所有的 #define 删除,并且展开所有的宏定义。
- 处理条件编译指令 #if、 #ifdef,、#elif、#else、#endif。
- 处理 #include,展开被包含的文件。
- 保留编译器需要使用的 #pragma 指令。
- 编译:对预处理文件进行词法分析,语法分析和语义分析。生成汇编文件(.s文件)。
- 编译:gcc -S hello.i -o hello.s 。
- 词法分析:分析关键字,标示符,立即数等是否合法。
- 语法分析:分析表达式是否遵循语法规则。
- 语义分析:在语法分析的基础上进一步分析表达式是否合法。
- 分析结束后进行代码优化生成相应的汇编代码文件。
- 汇编:将编译后的汇编文件翻译成目标文件(.o文件)。
- 汇编:gcc -c hello.s -o hello.o。
- 汇编器将汇编代码转变为机器的可执行指令。
- 每条汇编语句几乎都对应一条机器指令。
- 链接:C语言写的程序是需要依赖各种库的,编译之后还需要把库链接到最终的可执行程序中去。生成可执行文件, Windows下可执行文件的文件扩展名是exe。
- 链接:gcc hello.o -o hello 。
C语言的源代码文件就是一个普通的文本文件,但扩展名必须是 .c。创建一个. c文件:
#include <stdio.h>
#define MAX 100
int main() {
//这是第一个C语言程序
printf("hello world!\n");
printf("%d\n",MAX);
return 0;
}
-
#include头文件包含
#开头的一行代码是预处理指令;#include的作用是包含头文件;#include <stdio.h>的作用是包含头文件stdio.h。其作用相当于在预处理时将stdio.h文件中的所有内容都复制到代码所在的位置。使用C语言库函数需要提前包含库函数对应的头文件。要使用printf函数,就需要包含stdio.h头文件(stdio.h是标准输入输出头文件,stdio.h是C编译软件包的标准部分,它提供键盘输入和屏幕输出的支持)。
#include< > 与 #include " "的区别:
< > 表示系统直接按系统指定的目录检索。
" " 表示系统先在 " " 指定的路径查找头文件,如果找不到,再按系统指定的目录检索。 -
main函数
一个完整的C语言程序,由一个main函数(又称主函数,有且仅有一个)和若干个其他函数组合而成。程序是从main函数开始执行的,它是C语言程序的入口。“ int main(void) ” 中int 表明函数返回一个int值;main是函数名;圆括号表明main是一个函数;void表明函数不接受任何参数。 -
{} 花括号
C语言函数使用{}标记函数体的开始和结束。
一个{}的整体叫一个代码块,一个代码块内部可以有一条或者多条语句。 -
注释
注释通常用于对某处代码做简洁的说明,预处理时会自动忽视注释内容。
// 叫行注释,只能注释一行
/* */叫块注释,可以注释多行 -
printf函数
printf是C语言库函数,功能是向标准输出设备输出一个字符串。在这里是向显示器输出字符串,使用printf函数需要包含头文件stdio.h。
printf(“hello world\n”) 表示打印一行字符,\n表示回车换行,使下一次打印从下一行开始。 -
int num
int num 表示在main函数中声明一个名字为num的int类型的变量。 -
return语句
return语句表示函数执行完毕并返回一个值。 main函数中return 0 代表程序执行成功,return -1 代表程序执行失败。
VS集成开发环境
集成开发环境Visual Studio有自己的MSVC(Microsoft Visual C/C++)编译器。
由于微软在VS2013中不建议再使用C的传统库函数scanf、strcpy、sprintf等,直接使用这些库函数会提示C4996错误。VS建议采用带_s的函数,如scanf_s、strcpy_s等,但这些并不是标准C函数。要想继续使用标准C函数,可在源文件中添加以下指令:
#define _CRT_SECURE_NO_WARNINGS //最好放到.c文件的第一行
//或者
#pragma warning(disable:4996)
main函数的形式
- main()
没有指明返回类型的函数默认返回一个int类型。C90标准勉强接受函数省略返回类型, C99和C11标准不允许函数省略返回类型。因此,即使编译器允许,也应避免。 - void main()
某些编译器允许,但是所有标准都未认可这种写法。 - int main()
表示main是否接受参数是自由的。 - int main(void)
如果不接受参数,这是标准的形式。
标识符
标示符(IDentifier)是指用来标识某个实体的一个符号,C语言标识符分为三类
关键字
C语言已经预先规定了一批标识符,它们在程序中都代表着固定的含义,不能另作他用,这些标识符称为关键字。
预定义标识符
预定义标识符是指在C语言中预先定义并具有特定含义的标识符,如C语言提供的库函数名(如printf)和编译预处理命令(如include)等。 目前各种计算机系统的C语言都一致把这类标识符作为固定的库函数名或编译预处理中的专门命令使用,为了避免误解,建议用户不要把这些预定义标识符另作他用。
用户标识符
由用户根据需要定义的标识符称为用户标识符,又称为自定义标识符。 用户标识符一般用来给变量、函数、数组等命名。
标识符命名规范
- 标识符必须以字母a~z、 A~Z或下划线_开头,后面可跟任意个字符,这些字符可以是字母、下划线和数字,其他字符不允许出现在标识符中。
- 标识符区分大小写字母
- 标识符的长度,C89规定31个字符以内,C99规定63个字符以内
- C语言中的关键字不能作为标识符
- 自定义标识符最好取具有一定意义的字符串,便于阅读。