5.97k likes | 6.14k Views
高等教育出版社. 邹姝稚 等编著. 主要章节. 第 1 章 C语言概述 第 2 章 基本数据类型 、运算及表达式 第 3 章 顺序结构的C程序 第 4 章 分支结构的C程序 第 5 章 循环结构的C程序 第 6 章 数组 第 7 章 函数调用技术 第 8 章 预处理 第 9 章 指针 第 10 章 结构体与共用体 第 11 章 C数据文件. 2. 第 1 章 C 语言概述. 第 1 章. C 语言概述. 第 1 章 C 语言概述. 主要内容. 1.1 C语言出现的历史背景
E N D
高等教育出版社 邹姝稚 等编著
主要章节 第1章 C语言概述 第2章 基本数据类型、运算及表达式 第3章 顺序结构的C程序 第4章 分支结构的C程序 第5章 循环结构的C程序 第6章 数组 第7章 函数调用技术 第8章 预处理 第9章 指针 第10章 结构体与共用体 第11章 C数据文件 2
第1章 C语言概述 第1章 C语言概述
第1章 C语言概述 • 主要内容 1.1 C语言出现的历史背景 1.2 C程序的结构 1.3 C语言的特点 1.4 C语言程序的开发过程
第1章 C语言概述 1.1 C语言出现的历史背景 C语言起源可追溯到ALGOL 60。1960年出现的ALGOL 60是一种面向问题的语言。 1963年,剑桥大学将ALGOL 60发展成为CPL语言,但过大的规模使CPL难以实现。1967年剑桥大学的Matin Richards对CPL语言进行了简化,出现了CPL的简化版BCPL语言。 1970年,贝尔实验室的ken Thompson为寻求一种操作系统开发工具,以BCPL语言为基础,设计出很简单且接近硬件的一种语言,将其命名为“B语言”。 1972年,贝尔实验室的Dennis M.Ritchie在保持B语言精练性、可操作硬件等优点的同时,对其对于简单的功能进行加强,在B语言的基础上设计出C语言。 1975年,用C语言编写的UNIX 6公布后,C语言和UNIX操作系统引起了业内人士的广泛关注,C语言获得迅速发展。1983年ANSI推出C语言的第一个标准:ANSI C。1987年ANSI公布了新的C语言标准,该标准1990年被国际标准化组织接受为ISO C的标准(ISO9899-1990),成为现行的C语言标准。
第1章 C语言概述 1.2 C程序的结构 通过几个C程序的实例来认识和了解C程序的语法结构及其特点。 【例1.1】编写一个简单的C程序,输出显示字符串:This is a C program. 源程序如下: #include <stdio.h> void main() /*无参数的主函数*/ { /*函数体开始*/ printf(“This is a C program.\n”); } /*函数体结束*/ 【例1.2】编程计算两个整数的平均值。 源程序如下: #include <stdio.h> void main() /*一个求平均值的C程序*/ { int a,b; /*定义两个整型变量*/ float ave; /*定义实型变量*/ printf(”Input two integers:\n”); /*输入提示信息*/ scanf(”%d,%d”,&a,&b); /*输入a,b之值*/ ave=(a+b)/2.0; /*求平均值*/ printf(“Average=%.2f\n”,ave); /*输出平均值*/ } 6
第1章 C语言概述 1.2 C程序的结构 通过几个C程序的实例来认识和了解C程序的语法结构及其特点。 由例可概括出C程序的结构特点: 1.C语言是“函数式”语言,一个C程序由一个或多个函数构成。 C程序中总是包含一或多个用户编写的函数。C语言中,函数是组成C程序模块的惟一、基本的单位,模块之间的调用关系是通过C函数间的调用关系来实现的。 2.每个C程序必须有一个且只能有一个main函数。 main函数用以标识程序中的主函数,它指明程序执行的入口。 【例1.3】已知x=2,求当n=1,2,…10时,xn之值。 源程序如下: #include <stdio.h> int power(x,n) int x,n; { int i,p=1 ; for(i=1;i<=n;i++) p=p*x; return p; /*返回p值*/ } void main() { int j; printf(“n\tpower(2,n)\n”); for(j=1;j<=10;j++) printf( “%d\t%d\n”,j,power(2,j)); } 7
第1章 C语言概述 1.2 C程序的结构 3.可采用的C函数语法有K&R提出的经典语法和ANSI标准推出的函数原型语法两种。 (1)C函数经典语法 [函数类型] 函数名([形式参数列表]) [形式参数定义] { [内部变量定义] [语句]... } (2)函数原型语法 [函数类型] 函数名([形参类型 形参名1,形参类型 形参名2,…]) { [内部变量定义] [语句]... } 4.C函数中的语句表示为:[关键字] [语句体] ; 5.C语言风格的注释由/*和*/来限定。 8
第1章 C语言概述 1.3 C语言的特点 1.C语言语法简洁、紧凑,生成的目标代码质量高。 C语言语法简练,其书写中压缩了一切不必要的语法成份。因此,C源程序短小紧凑,经编译生成的目标代码质量高,执行速度快。 2.C语言将高级语言的编程功能和汇编语言的实用性有机结合。 在C程序中既可以构造出高级语言程序中的控制流,又可像汇编语言那样直接对硬件进行操作。例如,C语言通过位运算和指针运算,可以直接对内存物理地址进行操作。因此,C语言既具有高级语言的功能,又兼有汇编语言的大部分功能。 3.C语言运算符丰富,运算功能强大。 C语言共有45个运算符,分布在15个优先级上,能实现诸如:算术运算、赋值运算等13大类计算。运算符所表达的含义也极其丰富,除程序结构和I/O操作之外,几乎其它所有的程序功能都可以运用运算符构造表达式来加以表示。
第1章 C语言概述 1.3 C语言的特点 4.数据结构丰富。 C语言不仅提供有整型、实型、字符型、枚举型等基本数据类型,而且能在基本类型基础之上构造出诸如:数组、指针、结构体、共用体等复杂的数据类型。从而在程序中实现各种复杂的数据类型的运算。 5.C语言是结构化的程序设计语言。 C程序的模块化通过C函数以及函数间调用加以实现。在每个函数中,支持顺序结构、分支结构和循环结构的程序控制流,从而使得程序完全结构化。这也使得开发出的C程序结构清晰、可读性好。 6.C语言实现力求简单,其适用范围大、可移植性好。 C语言编译系统只提供编程所需的基本语句和控制流,而无I/O设施,这些功能通过库函数提供。这不仅使C语言本身的成份得到精简,也增强了C语言的通用性和可移植性。 10
第1章 C语言概述 1.4 C语言程序的开发过程 1. C程序运行步骤 C语言是以编译方式运行的高级语言。编写C程序并上机运行获得结果,必须经历编辑->编译->链接->运行四个步骤,每个步骤完成不同的功能并生成不同类型的文件,如图1.1所示。 图1.1 C程序运行的逻辑步骤 11
第1章 C语言概述 1.4 C语言程序的开发过程 1. C程序运行步骤 上述四个步骤中任何一步出错,都必须回到编辑步骤,修改程序后重新进行调试。编写一个正确的C程序,调试是一个反反复复的过程。图1.2以名为f.c的源程序运行为例,描述了C程序的调试过程。图中实线表示操作流程,虚线表示文件的输入输出。 图1.2 调试C程序的流程 12
第1章 C语言概述 1.4 C语言程序的开发过程 2.用Turbo C运行C程序的步骤 下面简单介绍用Turbo C 2.0运行一个C程序的主要操作步骤。 (1)启动Turbo C 在Windows环境下运行Turbo C ,只要在文件夹TC中双击TC.EXE即可。启动后的Turbo C主界面如图1.3所示。可以使用Alt+Enter键在全屏和Windows窗口之间进行切换。按F10键可进入主菜单,通过光标移动键选择下拉菜单可完成所需操作。 图1.3 Windows窗口下的Turbo C主界面 13
第1章 C语言概述 1.4 C语言程序的开发过程 2.用Turbo C运行C程序的步骤 (2)编辑源程序 进入编辑窗口的方法有3种,需要使用File菜单项的有关下拉菜单,图1.4给出了File菜单项中的各个下拉菜单。下面是启动编辑的3种方法: 图1.4 File菜单项组成 ①选择菜单“File/New”可建立一个新文件(临时文件名为NONAME.C),在此状态下,可编辑源程序。 ②选择菜单“File/Open”,系统会提示你打开一个文件,如输入的文件名不存在,则就相当于建立一个新文件。此时可在编辑窗口中输入源程序的内容。 ③选择菜单“Edit”直接进入编辑状态,在此状态下输入或修改源程序。 14
第1章 C语言概述 1.4 C语言程序的开发过程 2.用Turbo C运行C程序的步骤 (3)程序存盘 为防止意外丢失源程序,最好将程序存盘。可按F10键进入主菜单,选择File菜单项,接着使用Save命令(文件名不更名)或Write to命令(文件名可更名)将文件存盘。 (4)编译源程序 编译源程序方法有3种: ①选择“Compile/ Compile to OBJ”菜单进行编译,将得到和源程序同名扩展名为.obj的目标程序。 图1.5 Compile菜单项组成 ②按Alt+F9键一次性完成编译和链接。不仅会生成目标程序,还将生成与源程序同名而扩展名为.exe的可执行程序。 ③选择菜单“Compile/Make EXE file”,也可将编译和链接合为一个步骤进行。 15
第1章 C语言概述 1.4 C语言程序的开发过程 2.用Turbo C运行C程序的步骤 (5)运行程序 选择Run菜单可执行编译后的程序,具体有两种操作方法可供选择: ①选择菜单“Run/Run”,可启动程序运行。 ②使用Ctrl+F9快捷键。 (6)查看运行结果 图1.6 Run菜单项组成 可以选择菜单“Run/User Screen”或使用Alt+F5快捷键查看程序运行结果。此时程序界面消失,出现运行结果界面。当查看结果后,按任意键即可返回主界面。 16
第2章 基本数据类型、运算及表达式 第2章 基本数据类型、运算及表达式 17
第2章 基本数据类型、运算及表达式 • 主要内容 2.8 求字节数运算符 2.9 位运算 2.10 赋值运算 2.11 増、减1运算 2.12 逗号运算 2.1 C的数据类型 2.2 语法图的概念 2.3 标识符含义 2.4 常量与变量 2.5 基本数据类型 2.6 变量定义及其初始化 2.7 算术运算 18
第2章 基本数据类型、运算及表达式 2.1 C的数据类型 C语言提供的数据类型具体可以分为基本数据类型、构造数据类型、指针类型和空类型四大类。 图2.1 C语言数据类型 19
第2章 基本数据类型、运算及表达式 2.2 语法图的概念 语法图是语法的图语言表示法,用不同的图例表示一个语法中的各种基本成分。语法图的语义:在一个语法图中,从箭头入口到箭头出口,所有可能的路径集构成了该语法的全部合法形式。 图2.2 语法图中常用图例 例如:合法的字母字符是指26个大写英文字母’A’~’Z’或26个小写英文字母’a’~’z’的任一个。“字母字符”语法用语法图表示为图2.3。 图2.3 字母字符语法 20
第2章 基本数据类型、运算及表达式 2.3 标识符含义 标识符是程序中使用最为广泛的符号。是一个由有效字符序列组成的名字,该名字可以用来标识程序中的符号常量名、变量名、函数名、数组名和文件名等。 C语言规定标识符只能由字母、数字和下划线三种字符组合而成,且第一个字符必须是字母或下划线。若用语法图描述标识符的语法,如图2.4所示。 图2.4 标识符的语法图 21
第2章 基本数据类型、运算及表达式 2.3 标识符含义 例如:下面列出的均是合法的标识符,它们可用作程序中合法的符号常量名、变量名、数组名等: a、_、sum、s1、_above、day_of_year、lotus_1_2_3 下面均是不合法的标识符,在程序中使用将导致非法语法: d.m、a$、x1-1、2y、#33.3D、x>y 在使用标识符时,还应注意如下几点: 1.标识符的长度 虽然ANSI标准没有具体规定标识符的有效长度,但各个C编译系统都有着自己的规定。如IBM PC的MS C取8个字符,而TC 2.0则允许标识符长度为32个字符。标识符长度随系统而异,但至少前8个字符有效。如果超长,则超长部分不被识别而被舍弃。 2.标识符不能与关键字冲突 程序中用作标识符的名字,不仅要求合法,还要求不能与系统关键字同名。 22
第2章 基本数据类型、运算及表达式 2.3 标识符含义 3.注意大小写字母敏感问题 C语言中同一字母的大小写被认为是两个不同的字符。因此,诸如total、TOTAL和ToTal用作变量名时被认为是3个不同的变量。程序员在书写标识符时应该严谨。 4.提倡做到“见名知意” 在选择变量名或其它标识符时,应尽量做到“见名知意”。即选择有含意的英文单词或英文单词的缩写作为标识符。如count、name、year、month、sum等,除了数值计算程序外,一般不提倡使用代数符号,如a、b、c、x、y、z等作为变量名。这样,通过标识符的合理运可以有效增强程序的可读性。 23
第2章 基本数据类型、运算及表达式 2.4 常量与变量 所谓常量是指在程序运行过程中,其值不能被改变的量。如:100这种量在程序运行过程中其值不能改变,因此100就属于C程序中的常量。C语言中的常量也区分为不同的类型,一般从其字面书写形式上即可判别其类型,如12、0、-9为整型常量,4.6、-1.235为实型常量,’a’、’x’为字符常量等。 相对于常量,变量是指其值可以改变的量。每个变量均有惟一的变量名,并在内存中占据一定的存储单元,在程序运行过程中其单元中存放的数值可以被改变。 2.4.1 符号常量 在C程序开发过程中,常会遇到一个特定常量在程序多处频繁出现的情况。如下面例2.1中圆周率之值3.14,在计算圆周长、圆面积以及球体积时被多次使用。 24
第2章 基本数据类型、运算及表达式 2.4 常量与变量 【例2.1】编程求半径为r的圆周长、圆面积及球体积,其中圆周率取为3.14。 【算法分析】用变量l表示半径为r的圆周长,则有计算公式:l=2*3.14*r。用变量s表示半径为r的圆面积,则有计算公式:s=3.14*r*r。用变量v表示半径为r的球体积,则有计算公式:v=4/3*3.14*r*r*r。在程序实现中,先输入半径之值r,然后运用l、s、v的计算公式分别求出圆周长、圆面积及球体积,最后将l、s、v输出出来即可。 #include<stdio.h> void main() { float r, l, s, v; /*定义变量r、l、s、v*/ scanf(“%f”, &r); /*输入r之值*/ l=2.0*3.14*r; s=3.14*r*r; v=4.0/3.0*3.14*r*r*r; /*计算l、s、v之值*/ printf(“l=%f,s=%f,v=%f\n”,l,s,v); /*输出l、s、v*/ } 【程序说明】上述程序不足之处在于圆周率3.14的修改极为不便,比如意图将圆周率由3.14改为3.14159,则程序员必须对程序中出现的3.14逐一手动加以修改,这不仅使得程序修改麻烦,缺乏通用性,还可能在多次修改中出错。为了便于程序的调试和移植,使用符号常量来表示圆周率数据,可改进程序的上述不足。 25
第2章 基本数据类型、运算及表达式 2.4 常量与变量 2.4.1 符号常量 1.符号常量的定义 符号常量是指用标识符所代表的一个特定常量。在C语言中,符号常量使用宏定义命令#define加以定义,该命令的一般格式如下: #define 符号常量标识符 常量字符串 该命令的作用是告知编译系统,在程序中用符号常量来代替常量字符串。 例如通过使用: #define PI 3.14159 可以定义符号常量PI,该符号常量在程序中用以表示常量串3.14159。因此凡是程序中出现3.14159的地方均用PI代替。 26
第2章 基本数据类型、运算及表达式 2.4 常量与变量 2.4.1 符号常量 1.符号常量的定义 【例2.2】编程求半径为r的圆周长、圆面积及球体积。圆周率3.14使用符号常量表示。 【算法分析】程序中使用#define命令定义符号常量PI,使其代表圆周率3.14。 #define PI 3.14 #include<stdio.h> void main() { float r, l, s, v; scanf(“%f”, &r); l=2.0*PI*r; s=PI*r*r; v=4.0/3.0*PI*r*r*r; printf(“l=%f,s=%f,v=%f\n”,l,s,v); } 【程序说明】程序中对PI的使用称为“宏调用”,编译系统对该程序进行编译预处理时(编译前进行),将使用#define命令中的常量字符串去替换宏调用处的符号常量,这个过程称为“宏展开”。 27
第2章 基本数据类型、运算及表达式 2.4 常量与变量 2.4.1 符号常量 2.说明 (1)程序中符号常量的使用分为三个步骤:宏定义、宏调用、宏展开。首先使用#define命令定义用符号常量代表一个常量串,然后,程序中凡是出现常量串的地方均用符号常量代替,最后由编译系统将常量串在宏调用处实施宏展开。 (2)为醒目起见,符号常量通常用大写字母表示,以便与变量名相区别。但这并非是语法上的强行规定,符号常量也可使用小写字母。 (3)宏定义命令#define是C语言的一个预处理命令,而不是一个C语句,因此不能在行末加分号。如果加了分号则改变了宏定义命令的具体语义。 如:#define PI 3.14;命令表示PI在程序中代替3.14;而非3.14。则在计算:l=2.0*PI*r时,系统预处理时将其宏展开成l=2.0*3.14;*r而导致语法出错。 28
第2章 基本数据类型、运算及表达式 2.4 常量与变量 2.4.1 符号常量 3.使用符号常量的好处 (1)含义清楚,可以提高程序可读性。 符号常量通常是含义直观的大写标识符。如例2.2中,从字面上就可推断出PI为圆周率,远比数据3.14的含义清楚。在程序中使用“见名知义”的符号常量有助于提高程序可读性。 (2)便于程序的修改和维护。 使用简短醒目的符号常量代替一个常量字符串,可以减少程序中重复书写这个常量字符串的工作量。例如,如果不定义PI代表3.1415926,则在程序中多处出现3.1415926,不仅麻烦且易写错,而符号常量的简短直观特点减少了这种出错可能。而当需要改变常量串的数值时,可以只改变#define命令行,就达到“一改全改”的目的。 29
第2章 基本数据类型、运算及表达式 2.4 常量与变量 2.4.1 符号常量 3.使用符号常量的好处 【例2.3】设有宏定义: #define WIDTH 80 #define LENGTH WIDTH+40 则执行语句v=LENGTH*20;后,v的值是 。 【分析】语句v=LENGTH*20;在宏展开后变为v=80+40*20; 因此,v的值是880。 【例2.4】设有宏定义: #define WIDTH 80 #define LENGTH (WIDTH+40) 则执行语句v=LENGTH*20后,v的值是 。 【分析】语句v=LENGTH*20;在宏展开后变为v=(80+40)*20; 因此,v的值是2400。 30
第2章 基本数据类型、运算及表达式 2.4 常量与变量 2.4.2 变量 不同于常量,变量的值是可以被改变的。首先,每个变量都有区别于其它变量的变量名,编译系统将根据变量的类型为该变量分配一定的主存单元。此后,在程序中就可以通过变量名找到变量的内存地址,从中读取数据或将数据写入。 1.变量的两个要素 (1)变量名 变量的命名需遵循标识符命名规则,同时变量的命名应注意以下几点: ①变量名习惯上使用小写字母表示,如变量sum、year、average等,且不能使用关键字做变量名,如if、for、case等均是非法变量名。 ②变量的命名应尽量做到“见名知意”,即选用有含意的英文单词(或其缩写)作为变量名,以增强程序的可读性。 31
第2章 基本数据类型、运算及表达式 2.4 常量与变量 2.4.2 变量 1.变量的两个要素 (2)变量的类型 变量类型指变量内存单元中所能存放的数值类型。变量类型不仅决定该变量所占存储空间的大小,还决定对该变量所能进行的合法运算。 因此,在C语言中,所有变量必须“先定义,后使用”。定义变量的目的如下: ①凡未定义的变量,系统均不将其认作变量名,这样可保证变量名使用得正确。 例如: 若有定义:int student; 而程序中有语句stadent=30;错将student写成stadent。 则编译时就能检查出stadent未经定义,系统将给出“Undefined symbol stadent in function main”的提示信息。 32
第2章 基本数据类型、运算及表达式 2.4 常量与变量 2.4.2 变量 1.变量的两个要素 (2)变量的类型 ②变量被指定为一个类型,编译时就能根据类型为其分配相应的存储单元。 例如: 有定义语句: int number; 则Turbo C编译系统将为number分配2个字节的内存单元,并按整数方式存储其数据。 再如: 定义: char sex; 则Turbo C编译系统将为sex分配1个字节的内存单元,并按ASCII码方式存储其数据。 ③指定变量属于一种类型,编译时就能根据类型检查该变量进行的运算是否合法。 例如: 若有定义:float a,b,c;而在执行语句中对a、b进行求余运算c=a%b; 则由于不允许对实型数据执行“求余”运算,在编译时会给出有关“出错信息”。 33
第2章 基本数据类型、运算及表达式 2.5 基本数据类型 2.5.1 整型数据 整型数据分为整型常量和整型变量。 1.整型常量 整型常量就是整常数,在C语言中,整常数可以用十进制、八进制和十六进制3种进制形式表示。 图2.5整型常量语法图 34
第2章 基本数据类型、运算及表达式 2.5 基本数据类型 2.5.1 整型数据 例如: +123、-568、1627是合法的十进制整数。而以下各数不是合法的十进制整数: 023(不能有前导0)、23D(含有非十进制数码D)。 再如:015(十进制13)、0101(十进制65)、-012(十进制为-10)是合法的八进制整数。 而以下各数不是合法的八进制整数:256(无前缀0)、03A(包含了非八进制数码A)、O127(前缀是数字0而非字母O)、018(八进制没有数码8)。 再如:0X2A(十进制42)、-0xA0(十进制 -160)、0XCDF(十进制3295)、0x6Ac(十进制1708)是合法的十六进制整数。而以下各数不是合法的十六进制整数: 5AC(无前缀0x或0X)、0X33H(含有非十六进制数码H)。 1.整型常量 不难看出整型常量的两个语法特征: (1)在C语言中,不同进制的整型常量是通过不同的语法前缀加以区分的。 其中,十进制整数由数字0~9和正负号表示,不使用语法前缀。八进制整数由数字0开头,后跟数字0~7来表示,其采用数字0作为语法前缀。十六进制整数由0x或0X开头,后跟0~9、a~f或A~F来表示,其采用0x或0X作为语法前缀。 35
第2章 基本数据类型、运算及表达式 2.5 基本数据类型 2.5.1 整型数据 1.整型常量 针对上述三种整数表示方法,可以定义整数的符号常量,如: #define NUM1 20 /*符号常量NUM1代表十进制数20*/ #define NUM2 020 /*符号常量NUM2代表八进制数020*/ #define NUM3 0X20 /*符号常量NUM3代表十六进制数0X20*/ 其中常量NUM1代表的值是20,常量NUM2代表值16,常量NUM3代表值32。 (2)在C语言中,整型常量可以使用语法后缀l或L,表示其为长整型数据。 例如: 3是合法的十进制数、是基本整型数据;3l则是一个合法的长整型数据。 同样地,0123L、0Xffl、-0xcdl均为合法的长整型数。 在C程序中,长整型数主要用作函数调用时,实参和形参之间的类型匹配。如果函数的形参是长整型变量,则要求实参也是长整型数据。 36
第2章 基本数据类型、运算及表达式 2.5 基本数据类型 2.5.1 整型数据 2.整型变量 根据整型变量表示数值范围的不同,整型变量划分为基本整型、短整型和长整型三种。其中每一种类型又可加上修饰符signed或unsigned表示是有符号型或无符号型数据。因此,C语言中的整型变量归纳起来共分为6种类型,见图2.6。 图2.6 整型变量及其类型标识符一览 37
第2章 基本数据类型、运算及表达式 2.5 基本数据类型 2.5.1 整型数据 2.整型变量 (1)变量定义语句的格式: 类型标识符 变量名; 例如: 定义长整型变量l,可用下面任一语句: signed long int l; signed long l; long int l; long l; 以下是整型变量定义语句: unsigned int u; /*u是无符号整型变量*/ unsigned u; /*语义同上一语句*/ unsigned long int lu; /*lu是无符号长整型变量*/ unsigned long lu; /*语义同上一语句*/ 例如: 下面是基本整型变量定义的范例: signed int i; /* i是基本整型变量*/ 与上述语句等价的是: int i; 下面是短整型变量的一组等价定义语句: signed short int h; signed short h; short int h; short h; 38
第2章 基本数据类型、运算及表达式 2.5 基本数据类型 2.5.1 整型数据 2.整型变量 (2)六种整型变量可归纳成有符号型(signed)和无符号型(unsigned)两大类。 其中signed是可缺省符号,即若不指定unsigned时就是指定了signed。所谓signed或unsigned,是指如何看待数据的最高二进位。若将最高位当作符号位,则是signed;若果将存储单元中全部二进位都当作数据位,则是unsigned。 例如 以16位存放一个整型数据为例,-2机内补码=1111111111111110。 若定义:int a=-2;则-2机内补码的最高二进位被看做数的符号位,则a的值等于-2,数据表示是正确的。 若定义:unsigned b=-2;则-2机内补码的符号位被看做是数据的第1位,那么b的值被认作是65534,而不是-2,也就是说用无符号整型变量b存放-2是错误的(详见图2.7)。 39
第2章 基本数据类型、运算及表达式 2.5 基本数据类型 2.5.1 整型数据 2.整型变量 (2)六种整型变量可归纳成有符号型(signed)和无符号型(unsigned)两大类。 图2.7 有符号型与无符号型数据 由此可知,有符号整型变量可以正确地存放正整数或负整数,但无符号整型变量只能存放不带符号的正整数,如果将负数赋给一个无符号整型变量,将导致数值出错。 40
第2章 基本数据类型、运算及表达式 2.5 基本数据类型 2.5.1 整型数据 2.整型变量 (3)整型变量根据占据内存字节数的不同,又分成短整型、基本整型和长整型。 表2.1列出了ANSI标准定义的整型类型和取值范围,其中“最小取值范围”是指不能低于此值,但可以高于它。 表2.1 ANSI标准定义的整数类型 41
第2章 基本数据类型、运算及表达式 2.5 基本数据类型 2.5.1 整型数据 2.整型变量 (4)整型数据的溢出问题 由表2.1可知,每种整型变量都有所能表示的数值范围,若传递给变量的数据超出该范围,就不能正确地表示数据,这种现象称为“溢出”。 【例2.5】分析下列程序的运行结果。 #include <stdio.h> void main() { int a,b; a=32767; b=a+1; printf(“a=%d,b=%d\n”,a,b); } 图2.8 整型数据溢出图示 【分析】程序运行结果为:a=32767,b=-32768 (注:b的值不是预期的32768,产生溢出现象) 导致这一错误的原因在于:32767是基本整型数据的最大取值,将a+1后送入b即溢出,见图2.8。 42
第2章 基本数据类型、运算及表达式 2.5 基本数据类型 2.5.1 整型数据 2.整型变量 【例2.6】分析下列程序的运行结果。 【程序1】 #include <stdio.h> void main() { int i; i=50000; printf(“i=%d\n”,i); } 【程序2】 #include <stdio.h> void main() { unsigned i; i=50000; printf(“i=%u\n”,i); } 【分析】程序1中,由于50000已超过基本整型数据的数值范围,因此产生溢出错误,程序运行结果将是i=-15536。 程序2中,将变量i定义成无符号整型变量,则i可以正确表示出50000,因此,程序2能获得正确的运行结果:i=50000。 43
第2章 基本数据类型、运算及表达式 2.5 基本数据类型 2.5.1 整型数据 2.整型变量 (5)将一个整型常量赋值给变量时应注意类型匹配。 如同整型变量有不同类别之分,整型常量按其值所在范围的不同也区分成不同类别。在将一个整型常量赋值给变量时应注意类型匹配。 例如一个整数,如果其值在-32768~32767范围内,则认为其为int型,可以将其赋值给int型或long int型变量。 如果一个整数之值超过了上述范围,而在-2147483648~+2147483647范围内,则认为其为长整型,为保证数据传送的正确性,必须将其赋值给一个long int型变量。 如果一个整型常量加以后缀l或L,则是长整型,只能赋值给长整型变量。 44
第2章 基本数据类型、运算及表达式 2.5 基本数据类型 2.5.2 实型数据 1.实型常量语法 (1)十进制小数形式:由正负号、数字0~9和小数点组成(必须有小数点)。 例如:3.14、0.8、0.0、-36.625、+100.0等 都是正确的十进制小数形式。 (2)指数形式:由正负号、数字0~9、小数点和字母e(或E)组成。一般语法形式为:±xe±n或±xE±n,表示的数值是±x×10±n。 例如:3.14e5、123e-4、1E5、.89e9.78e-6均是正确的实数。 而:e3、.e5、4.5e、123e4.0均是非法实数。 一个实数可以有多种指数表示形式,“规范化的指数形式”满足1.0≤x<10。 例如:123.456可以表示为123.456e0、12.3456e1、1.23456e2、0.123456e3或0.0123456e4等,其中的1.23456e2称为“规范化的指数形式”。 45
0 101 1000 0000 0000 0000 0000 0000 0010 符号位 尾数部分(23位) 阶码部分(8位) 第2章 基本数据类型、运算及表达式 2.5 基本数据类型 2.5.2 实型数据 2 实型变量 (1)实型数据在内存中的存放形式 实型数据在内存是按指数形式存放的。系统将实型数据所占32位分成三个部分:最高位是尾数的符号位,也是整个实数的符号位;剩下的31位一部分存放实数的尾数部分;另一部分用于存放实数的阶码部分。 例如:以实数68.75为例,68.75=0.6875×102, 尾数x=(0.6875)10=(0.10110000000000000000000)2,阶码n=(2)10=(00000010)2,因此,实数68.75的内存存放形式如图2.9所示。 图2.9 实数68.75的内存存放形式 46
第2章 基本数据类型、运算及表达式 2.5 基本数据类型 2.5.2 实型数据 2 实型变量 (2)实型变量分类和定义 实型变量分为单精度型和双精度型两种,其类型标识符、内存分配字节数、有效数字位和值域见表2.2。 表2.2 实型变量类型 例如:可定义如下实型变量: float f1=3.14,f2; (指定f1和f2是单精度实型变量,各在内存占用4个连续字节,其中f1被初始化为数值3.14) double z; (指定z是双精度实型变量,在内存占用8个连续字节) 47
第2章 基本数据类型、运算及表达式 2.5 基本数据类型 2.5.2 实型数据 2 实型变量 (3)实型数据的精度及舍入误差 实型数据提供的有效数字是有限的,有效数位以外的数字将被舍去。因此,一个十进制实数不一定能用二进制数精确表示,而有可能会产生一些误差。 【例2.7】实型变量的精度。 #include <stdio.h> void main() { float a; /*定义float型变量a*/ double b,c; /*定义double型变量b和c*/ a=123.456789; b=a; c=123.456789; printf(“a=%f,b=%f,c=%f\n”,a,b,c); } 【分析】 a的值将显示为123.456787而不是其精确值123.456789,因为float型变量只能保证7位有效数字,而对于double型变量,由于能表示16位有效数字,因此,变量c能将123.456789精确的输出出来。 48
第2章 基本数据类型、运算及表达式 2.5 基本数据类型 2.5.2 实型数据 2 实型变量 (3)实型数据的精度及舍入误差 【分析】 从理论分析上,b的值应为12345678920,而事实上,该程序所能获得的b的值与a相等,都是12345678848.000000。究其原因,仍然是由于一个float型变量,只能保证的有效数字是7位,后面的数字是无意义的,因此a并不能准确地表示出数据12345678900。对于这个数来说,前8位是准确的,后几位是不准确的,把20加在后几位上是无意义的。 【例2.8】实型变量的舍入误差。 #include <stdio.h> void main() { float a,b; a=123456.789e5; b=a+20; printf(“f\n”,b); } 49
第2章 基本数据类型、运算及表达式 2.5 基本数据类型 2.5.3 字符型数据 1.字符常量 字符常量有两种表示形式:一种是用单引号括起一个ASCII字符,另一种是用单引号対括一个转义序列(该转义序列表示一个字符)。字符常量语法如图2.10所示。 例如:下面是合法字符常量的例子: ‘x’、’0’、’-‘ (分别表示字符x,数字字符0和负号字符-) ‘\n’ (用转义序列\n表示的一个字符,该字符是回车换行字符) ’\33’ (用转义序列表示的一个字符,该字符ASCII值的八进制值是33) ’\x10’ (用转义序列表示的一个字符,该字符ASCII值的十六进制值是10) 图2.10字符常量语法图 50