上章解释了 C 语言处理的标准输入输出设备。本章讲解 C 程序员如何创建、打开、关闭文本或二进制文件进行数据存储。 文件代表字节序列,无论文本或二进制文件。C 提供高级函数和低级(OS 级)调用处理存储设备文件。本章介绍文件管理重要调用。 打开文件 使用 fopen() 函数创建新文件或打开现有文件。此调用初始化 FILE 类型对象,包含控制流所需所有信息。原型: FILE *fopen( const char * filename, const char * mode ); filename 为字符串字面量,用于命名文件;mode 可取以下值: 序号模式及说明 1r以读方式打开现有文本
输入指向程序提供数据,可来自文件或命令行。C 提供内置函数集读取输入并按需提供给程序。 输出指在屏幕、打印机或文件显示数据。C 提供内置函数集将数据输出到屏幕并保存为文本或二进制文件。 标准文件 C 语言将所有设备视为文件。显示器等设备以同文件方式寻址,程序执行时自动打开以下三个文件提供键盘和屏幕访问: 标准文件文件指针设备 标准输入stdin键盘 标准输出stdout屏幕 标准错误stderr屏幕 文件指针是访问文件读写的手段。本节解释如何从屏幕读值及在屏幕打印结果。 getchar() 与 putchar() 函数 int getchar(void) 从屏幕读取下一个可用字符并作为整数
C 语言提供关键字 typedef,可为类型起新名字。例如为单字节数定义术语 BYTE: typedef unsigned char BYTE; 此类型定义后,标识符 BYTE 可作为 unsigned char 类型的缩写,例如: BYTE b1, b2; 惯例用大写字母提醒用户该类型名实为符号别名,但也可用小写: typedef unsigned char byte; 可用 typedef 为用户定义数据类型命名。例如配合结构体定义新数据类型,直接用该类型定义结构体变量: Live Demo #include <stdio.h> #include <str
假设 C 程序包含若干 TRUE/FALSE 变量,归组在结构体 status 中: struct { unsigned int widthValidated; unsigned int heightValidated; } status; 此结构需 8 字节内存,但实际每变量只存 0 或 1。C 语言提供更好方式利用内存。 若在结构体内使用此类变量,可定义变量宽度,告诉编译器仅使用指定位数。上例可重写为: struct { unsigned int widthValidated : 1; unsigned int heightValidated : 1; } status; 上结构
联合体 是 C 语言特殊数据类型,允许在同一内存位置存储不同数据类型。可定义多成员联合体,但任一时刻只能有一个成员包含值。联合体提供同一内存位置多用途的高效方式。 定义联合体 定义联合体须使用 union 语句,方式同定义结构体。union 语句为程序定义包含多成员的新数据类型。union 语句格式: union [union tag] { member definition; member definition; ... member definition; } [one or more union variables]; 联合体标记 可选,每个成员定义为普通变量定义,如 int i;
数组允许定义可容纳多个同类数据项的变量类型。类似地,结构体 是 C 语言另一种用户定义数据类型,允许组合不同种类的数据项。 结构体用于表示记录。假设要跟踪图书馆图书,可能需记录每本书的以下属性: 标题 作者 主题 书号 定义结构体 定义结构体须使用 struct 语句。struct 语句定义新数据类型,包含多个成员。struct 语句格式: struct [structure tag] { member definition; member definition; ... member definition; } [one or more structure variables]; 结
字符串实为以空字符 \0 结尾的一维字符数组。因此空终止字符串包含组成字符串的字符,后跟一个空字符。 下面声明初始化创建包含 Hello 的字符串。为在数组末尾容纳空字符,字符数组大小比单词 Hello 字符数多 1。 char greeting[6] = {H, e, l, l, o, \0}; 遵循数组初始化规则可写作: char greeting[] = Hello; 上述字符串在 C/C++ 中的内存表示: 实际上不必在字符串常量末尾手动放置空字符。C 编译器初始化数组时自动在末尾添加 \0。尝试打印上述字符串: Live Demo #include <stdio.
C 语言指针易学且有趣。某些编程任务用指针更容易,动态内存分配等任务离不开指针。因此学习指针是成为合格 C 程序员的必要步骤。让我们循序渐进学习。 众所周知,每个变量都是内存位置,每个内存位置有其地址,可用取地址运算符 & 访问。下例打印变量地址: Live Demo #include <stdio.h> int main () { int var1; char var2[10]; printf(Address of var1 variable: %x\n, &var1 ); printf(Address of var2 variable: %x\n, &
数组是一种数据结构,可存储固定大小的同类型元素顺序集合。数组用于存储数据集合,但更有用的是将其视为同类型变量的集合。 无需声明单个变量如 number0、number1... number99,只需声明一个数组变量 numbers,用 numbers[0]、numbers[1]... numbers[99] 代表单个变量。数组特定元素通过索引访问。 所有数组由连续内存位置组成。最低地址对应第一个元素,最高地址对应最后一个元素。 声明数组 C 语言声明数组需指定元素类型和元素数量: type arrayName [ arraySize ]; 这称为一维数组。arraySize 必须大于零的
作用域是程序中定义变量可存在的区域,超出该区域变量不可访问。C 语言中变量可声明在三处: 函数或块内部,称为局部变量。 所有函数外部,称为全局变量。 函数参数定义中,称为形式参数。 下面理解局部、全局变量和形式参数。 局部变量 在函数或块内声明的变量称为局部变量。仅能被该函数或代码块内的语句使用。局部变量对其自身以外的函数不可见。下例展示局部变量用法,变量 a、b、c 均为 main() 函数局部。 Live Demo #include <stdio.h> int main () { /* local variable declaration */ int a, b; in
函数是一组共同完成任务的语句。每个 C 程序至少有一个函数 main(),简单程序可定义额外函数。 可将代码分割到不同函数。如何分割由你决定,但逻辑上每个函数应执行特定任务。 函数声明告知编译器函数名、返回类型和参数。函数定义提供函数实际主体。 C 标准库提供许多内置函数,如 strcat() 连接字符串、memcpy() 复制内存等。 函数也称为方法、子程序或过程等。 定义函数 C 语言函数定义通用形式: return_type function_name( parameter list ) { body of the function } 函数定义包含函数头和函数体。函数各部分: 返
有时需要多次执行一段代码。通常语句顺序执行:函数中第一条语句先执行,接着第二条,依此类推。 编程语言提供各种控制结构实现更复杂的执行路径。 循环语句允许执行一条或一组语句多次。下图为大多数语言中循环语句的通用形式: C 语言提供下列循环类型: 序号循环类型及说明 1while 循环在给定条件为真时重复执行语句或语句组。执行循环体前测试条件。 2for 循环多次执行语句序列,简化循环变量管理代码。 3do...while 循环类似 while 语句,但条件测试在循环体末尾进行。 4嵌套循环可在任何 while、for 或 do..while 循环内使用一个或多个循环。 循环控制语句 循环控
决策结构要求程序员指定一个或多个条件供程序评估测试,并指定条件为真时执行的语句,可选地指定条件为假时执行的语句。 下图展示了大多数编程语言中典型决策结构的通用形式: C 语言将任何非零和非空值视为true,若为零或空则视为false。 C 语言提供下列决策语句: 序号语句及说明 1if 语句由一个布尔表达式后跟一条或多条语句组成。 2if...else 语句if 语句可跟随可选的else 语句,当布尔表达式为假时执行。 3嵌套 if 语句可在一个 if 或 else if 语句内使用另一个 if 或 else if 语句。 4switch 语句允许变量针对值列表进行相等性测试。 5嵌套 s
运算符是告诉编译器执行特定数学或逻辑运算的符号。C 语言内置运算符丰富,提供下列类型: 算术运算符 关系运算符 逻辑运算符 位运算符 赋值运算符 杂项运算符 本章逐一讲解各运算符工作方式。 算术运算符 下表列出 C 语言支持的所有算术运算符。假设变量 A 为 10,变量 B 为 20: 显示示例 运算符描述示例 +两操作数相加A + B = 30 -第一操作数减第二操作数A - B = -10 *两操作数相乘A * B = 200 /分子除以分母B / A = 2 %取模运算符,整数除法后余数B % A = 0 ++自增运算符,整数值加 1A++ = 11 --自减运算符,整数值减 1A
存储类定义 C 程序中变量和/或函数的作用域(可见性)和生命周期。它们位于所修饰类型之前。C 程序有四种存储类: auto register static extern auto 存储类 auto 是所有局部变量的默认存储类。 { int mount; auto int month; } 上例在同一存储类中定义两个变量。auto 只能用于函数内,即局部变量。 register 存储类 register 存储类用于定义应存储在寄存器而非 RAM 中的局部变量。这意味着变量最大尺寸等于寄存器大小(通常一个字),不能对其应用一元 & 运算符(因无内存位置)。 {
常量指程序执行期间不得修改的固定值,也称为 字面量。 常量可以是基本数据类型中的任意一种:整数常量、浮点常量、字符常量、字符串字面量。也有枚举常量。 常量像普通变量一样处理,只是定义后值不能修改。 整数字面量 整数字面量可以是十进制、八进制或十六进制常量。前缀指定基数:0x 或 0X 表示十六进制,0 表示八进制,无前缀表示十进制。 整数字面量也可以有后缀,由 U 和 L 组合表示 unsigned 和 long。后缀大小写不敏感,顺序任意。 整数字面量示例: 212 /* 合法 */ 215u /* 合法 */ 0xFeeL /* 合法 */ 078 /* 非法:8 非八进制数字 */ 03
变量是程序可操作的存储区域名称。C 中每个变量有特定类型,决定其内存大小布局、可存储值范围及可应用操作集。 变量名由字母、数字、下划线组成,必须以字母或下划线开头。大小写字母不同,因 C 区分大小写。基于前章基本类型,有以下基本变量类型: 序号类型及描述 1char通常单字节。属整数类型。 2int机器最自然整数大小。 3float单精度浮点值。 4double双精度浮点值。 5void表示类型缺失。 C 还允许定义其他变量类型,后续章节覆盖枚举、指针、数组、结构、共用体等。本章仅学习基本变量类型。 C 语言变量定义 变量定义告诉编译器在何处创建变量存储及创建多少存储。变量定义指定数据类型
C 语言数据类型是用于声明不同类型变量或函数的庞大系统。变量类型决定其占用存储空间大小及位模式解释方式。 C 语言类型可分类如下: 序号类型及描述 1基本类型属于算术类型,进一步分为:(a) 整数类型 (b) 浮点类型。 2枚举类型也是算术类型,用于定义只能在程序中赋特定离散整数值的变量。 3void 类型类型说明符 void 表示无可用值。 4派生类型包括 (a) 指针类型 (b) 数组类型 (c) 结构类型 (d) 共用体类型 (e) 函数类型。 数组类型和结构类型统称聚合类型。函数类型指定函数返回值类型。下节介绍基本类型,其他类型后续章节覆盖。 整数类型 下表提供标准整数类型的存储大
了解 C 程序基本结构后,易于理解其他基础构建块。 C 语言中的 Token C 程序由各种 token 组成,token 可以是关键字、标识符、常量、字符串字面量或符号。例如下面 C 语句包含五个 token: printf(Hello, World! \n); 单个 token 为: printf ( Hello, World! \n ) ; 分号 C 程序中分号是语句终止符。每条独立语句必须以分号结尾,表示一个逻辑实体结束。 下面两条不同语句: printf(Hello, World! \n); return 0; 注释 注释是 C 程序中的辅助文本,被编译器忽略。以 /* 开始,以 *
学习 C 语言基本构建块前,先看最简 C 程序结构,作为后续章节参考。 Hello World 示例 C 程序基本包含以下部分: 预处理命令 函数 变量 语句与表达式 注释 打印 Hello World 的简单代码: 在线演示 #include <stdio.h> int main() { /* my first program in C */ printf(Hello, World! \n); return 0; } 分析上述程序各部分: 第一行 #include <stdio.h> 是预处理命令,告诉 C 编译器在实际编译前包含 st
C语言