1
一、基本语言元素二、基本数据类型三、算术负运算与补码转换
2
一、基本语言元素
1,C/C++中的字符集每一种语言有各自的基本元素。
C/C++语言的词法分析建立在对基本元素的扫描、上下文匹配和排列组合之上。
基本类型是 C++作为强类型语言处理各种数据的基本尺度。
通过基本元素和类型完成文字符号的转换以及源头处的求值计算。
关于基本元素的约定就形成词法规定,由此形成定义、
声明、表达式、语句和函数进而建立完整的程序。
3
C/C++中的字符集由下列字符构成:
a,26个大小写英文字母,a~z,A~Z
b,10个数字字符,0~9
c,标点符号,空格 ~ ! # % ^ & * ( ) _ - +
= { } [ ],; ' ",< >,/?
\ |
C/C++中的标点符号对编译器而言具有词法意义,某些标点符号为 C/C++的运算符或对预处理器有重要意义。标点符号 [ ],( )和 { }必须成对出现。
C/C++中的字符集一共 91个字符,实际上包含可键入的字母,只有三个例外它们是,@,$,` 。
4
2.语言符号语言符号是 C/C++语言有意义的最小单元,
a,空白字符,空格、水平制表、换行、回车、换 页、
纵向制表和换行符都称为空白字符
b,标识符,所有的名称在索引点前必须先有效的说明
c,关键字,关键字是系统预定义的保留标识符
d,标点符号和分隔符 ;
e,文字常数 ;
f,运算符 ;
5
(1) 空白字符空格、水平制表、换行、回车、换页、纵向制表
(vertical tab)和换行 (newline)符都称为空白字符 (white-
space),它们具有相同的功能即作为打印页上单词和行之间的空白。
通过空白字符和其它语言符号,例如运算符和标点,从而对语言符号进行定界。
对代码进行词法分析时,编译器忽略空白字符,除非它们作为分隔符或字符串的组成成分。
6
(2)标识符所有的名称在索引点前必须先有效的说明,否则是无效的标识符。
标识符是程序员引入的有效的名称,是编译器许可的名称。
对象名、变量名或函数名,结构名、类类型名、枚举名、联合名或成员名,typedef名称、标号名、宏名、宏形参名、形参名等遵循标识符的命名规定。
7
标识符或名称的命名规定如下:
a,标识符的字符序列仅由下划线,_”、数字 0~9与 26个大小写字母 a~z,A~Z构成。
b,标识符的首字符必须是大写字母或小写字母或一个下划线,_”而不能是数字开头。
c,标识符不能与关键字使用一样的拼写和大小写方式。
d,标识符对大小写字母敏感,即大写字母或小写字母代表不同的名称。
例如,fileName和 FileName是不同的名称。标识符中含有关键字是合法的,例如 pint是一个合法的标识符,尽管它包含了关键字 int。而 1ab,&x,#ddd,9y不是有效的标识符。
8
(3)关键字关键字是系统预定义的保留标识符。
它们不能再定义用作程序中的标识符。
关键字是语言标准的制定者提供给用户使用的举足轻重的语言单词。
ANSI C89规定 32个保留字,C++在此基础上增添了以斜体表示的 28个关键字。
9
以下是这些关键字和其主要作用的非严格归类:
1.基本类型 char int float
double long short
signed unsigned bool
2.自引入类型 class enum struct union
3.内存大小和类名声明 sizeof typedef
4.存储属性 auto register static extern
5.数据冻结和变动 const volatile mutable
6.逻辑真假 false true
7.运算符和内存操作 operator new delete this
10
8.流程语句的控制 try throw catch if
else do while for
continue switch case
default break goto
return
9.成员访问控制 private protected public friend
10.函数修饰词 void inline virtual explicit
11.模板和名称空间 template typename
namespace using
12.类型转换运算 const_cast dynamic_cast
reinterpret_cast static_cast typeid
11
(4) 分隔符分隔符是用来分隔单词或程序正文的,它用来表示某个程序段的结束和另一个程序段的开始,或者增加程序的可读性。常用的分隔符如下所述:
a.圆括号 () 圆括号用于增加程序的可读性以及提高表达式运算的优先级。
b.空格符 常用来作为名称和名称或运算符之间的分隔符。
c.逗号,逗号用来作为定义多个变量之间的分隔符;
或者用来作为函数的多个参数之间的分隔符。逗号还可以用作运算符 。
12
d.分号; 用于循环语句中 for关键字后面括号中三个表达式的分隔,用于终止分号前的语句。花括号 { }后的分号表示一个声明的结束。
e.冒号,用来作语句标号与语句之间的分隔符和
switch语句中关键字 case与语句序列之间的分隔符。用于表示继承的上下关系、构造函数的冒号语法和访问作用界定。
f.花括号 {} 用来构造程序,形成程序块的层次体系。
g,省略号,..,三个圆点构成的省略号用来声明函数的可变参数。
13
(5)文字常数文字常数是在程序中直接使用字符序列表示的数据,
文字常数亦简称为常数或文字。
文字常数有整型常数、浮点常数、字符常数、字符串常数。
14
二、基本数据类型数据状态的数学描述形成数据结构,数据的操作是对数据的状态进行改变,通过特定的操作步骤数据从一种状态变成另一种状态,这些操作步骤就形成一套算法,因此程序是由数据结构与建立其上的相应算法构成的。
不同的数据结构对应不同的算法,这是所有计算机语言共有的特征。本课件用 type或 T,T1,T2,Tn等代表类型名。
type或 T1,T2可以是 char,short,int,long等整型和
float,double,long double浮点型或结构名,联合名,枚举名和类类型名等,它们可先通过 struct,class,enum,union或
Typedef 等声明。
15
数据类型基本数据类型指针类型 type* (含 void*)
引用类型 type& (无 void数据更无 void&数据 )
枚举类型 enum (枚举常数为有限个 int型常数 )
集合数据类型 数组类型 array [ ]
结构类型 struct
联合类型 union
类类型 class
整型 int short long
字符型 char(属于 1字节的整型 )
单精度浮点型 float
实型 双精度浮点型 double
长 双精度浮点型 long double
布尔逻辑型 bool
16
类型名 type 说明 长度 数据范围
bool 布尔逻辑型 1 true (1) false(0)
char 字符型 l -128~127 (0~255)
unsigned char 无符号字符型 1 0~255
signed char 有符号字符型 1 -128~127
[signed] short [ int] 有符号短整型 2 -32768~32767
unsigned short [ int] 无符号短整型 2 -32768~32767
[signed] int 有符号整型 2/4 -32768~32767
unsigned [int] 无符号整型 2 /4 0~65535
[signed] long [int] 有符号长整型 4 -2147483648~2147483647
unsigned long [int] 无符号长型型 4 0~4294967295
float 浮点型 4 3.4*10e-38~~3.4*10e38
double 双精度型 8 1.7*10e-308~~1.7*10e308
long double 长双精度型 8/ 10 至少与 double类型同
17
描述数据的状态首先要获得数据的类型,通过引入变量的概念来确定数据的状态。
变量是存储信息的单元,它对应于某个内存空间。变量名代表其存储空间,程序能在变量中存储值和取出值。在定义变量时,说明的变量名称和数据类型 (如 int)告诉编译器要为变量分配多少内存空间,以及变量中要存储什么类型的值。内存单元的单位是字节。
C++是一门强数据类型的语言,每一种数据一般都严格地对应确定的数据类型。 C/C++的数据类型有基本数据类型和非基本数据类型之分。基本数据类型是 C/C++内部预先定义的数据类型,非基本数据类型包括指针、数组和结构以及类类型等,非基本数据类型也称用户引入的数据类型。
18
基本数据类型有:
char (字符型 ),int (整型 ),float (单精度浮点型 )和
double (双精度浮点型 )。在 ANSI C++中,还有 bool(布尔型 ),bool类型的变量其结果值用真 true假 false表示,true
就是 1,false就是 0。
关键字 char,int,float,double和 bool等为基本数据类型的类名。类名不占内存空间。关键字 void具有特殊的含义,因为没有 void型的数据,只有 void*型的指针。
除上述基本数据类型外,还有一些类型修饰符,它用来改变基本类型的意义。
修饰符有 1ong(长型符 ),short(短型符 ),signed(有符号 )和 unsigned(无符号 )。
19
short只修饰 int,short int可省略为 short,long修饰
int和 double,1ong int可省略为 1ong,一般表示 4个字节,
修饰 long double时,一般表示 8或 10个字节。
unsined和 signed能修饰 char,short,int和 long。数据类型确定了数据所占内存空间大小,也确定了数据的范围。
数据类型的数域范围记录在头文件 limits,h和 float,H
中。 int类型必然不小于 short类型,不大于 long类型,在 16
位系统里是 2个字节长,32位系统里为 4个字节长。
整数类型包括 char,short,long,signed,unsigned
等。
枚举常数和当作右值使用的枚举变量可视为 int类型看待。
20
float类型是 4字节的浮点数。
double是 8字节的浮点数,也是 32位浮点数学协处理器进行表达式运算的标准类型,double类型是浮点数的缺省类型,float类型的数据一般会转换到 double类型的数据进行运算。
浮点类型包括 float,double和 long double类型。
long doulbe 类型表示浮点处理器的幕后精度和数据范围的扩充优化处理,当程序员感到 64位 double内存不足以处理符点数的运算时,就设置 long double 变量。以便编译器启动 80位的内部临时运算寄存单元。
21
微软编译器的 long double变量只占 8字节的内存,但
long double和 double是不同的数据类型。
字符型整型浮点型统称为算术类型。
这样数据的状态通过变量来索引,变量由这里介绍的类型名引入,通过定义语句分配内存。 例如:
double d; short s; long n;
变量 d具有类型属性 double,其数据占有 8字节的内存。
short型变量 s具有 2字节内存,long型变量 n具有 4字节内存。
22
三、算术负运算与补码转换一个十进制数可以用字符串抽象的表示为:
具体展开为:
字符串中的字符就限制在 0,1,2,3,4,5,6,7,8,9十个字符数码中取值。十进制数的基数为 10。遵循逢十进一的运算规则。 10k 称为第 k+1位数字的权。
mnn cccddd 2101,
)101010101010( 22110011 mmnnnn cccddd
23
例如,,是第 3位数的权,其结果是三位数的值。一般地基数为 r的 r进制数的值可以表示为,
其含义就是:
其中可以是 0,1,2,...,r-1中的数码,rk称为第 k+1位数字的权即以 r为底的 k次幂,遵循逢 r进位的原则。
这样从上面一般的公式得到二进制数的值为,
整型数分有符号和无符号两种。无符号整数的最高的位数为该数的有机组成部分。
有符号整数其最高的位用于识别数的正负,最高为 0表示一个正数,1则表示负数。
a a a b b bn n m? 1 0 1 2.
)( 22110011 mmnnnn rbrbrbrarara
)222222( 22110011 mmnnnn bbbaaa
200 = 2 10 2? 102
24
例如,8位长的二进制数 00000001b=+1d,01111111b=+127d,
00000000b=-127d
正数不做补码原码转换,即正数的原码、补码相同。
例如,对于二进制数 11111111可以理解为无符号数的 255,也可以理解为原码 -127,同时可以视为 -1的补码。
求补的含义分为两种,一种是直接求补,另一种是间接求补。
直接求补是 C/C++语言的单目算术负运算,其含义为对于一个数取补就是对单目操作数按位求反最低位加 1,按位求反操作就是 1切换为 0,0切换为 1。算术负运算的源操作数无论数的正负。
25
例如:
2进制数 16进制数 2进制数 16进制数原操作数,11000011 c3 00111101 3d
按位取反 00111100 3c 11000010 c2
最低位加 1 00111101 3d 11000011 c3
十六进制数 3d直接求补的结果为 c3。十六进制数 c3
直接求补的结果为 3d。
例如语句:
printf ("0x%x,0x%x\n",-0x10234567,-0xefdcba99);
输出结果,0xefdcba99,0x10234567
从上可以看出直接求补偶次得到原来的操作数。
26
间接求补运算仅对最高位为 1的有符号数进行。当内存数据最高位为 1时,如果需要执行有符号数的转换,以便得到这个数的原码,间接求补运算发生作用。
间接求补的运算规则可根据下面二个步骤进行:
1,将最高位的 1变为 0,这就是取负数的绝对值。
2,对负数的绝对值执行直接求补运算。
例如对于最高位为 1的 16进制数 ae,d2的二次求补为:
16进制数 2进制数 16进制数 2进制数数据的原值 ae 10101110 d2 11010010
最高位清 0 2e 00101110 52 01010010
按位取反 d1 11010001 ad 10101101
最低位加 1 d2 11010010 ae 10101110
27
下面两个步骤也可以得到最高位为 1的数 (视为负数 )的原码,
1,对负数进行直接求补运算。由此得到负数原码的绝对值
2,将最高位设置为 1。这也就是在负数的绝对值之前加上负号例如对于最高位为 1的 16进制数 (视为负数 ) ae,d2的间接求补可以运算为:
16进制数 2进制数 16进制数 2进制数数据原值 ae 10101110 d2 11010010
按位取反 51 01010001 2d 00101101
最低位加 1 52 01010010 2e 00101110
最高位置 1 d2 11010010 ae 10101110
28
16进制数 d2间接求补的结果 ae,16进制数 ae间接求补为
d2。
16进制数负数 ae的原码为 d2,d2的绝对值为 01010010即
0x52。也就是说对于内存的原始十六进制数据 ae,当作有符号字符数输出时 d2是这个数的原码,最高位当作符号位处理。
例如,
printf ("0x%hx,%d,%d\n",0xae,(signed char)0xae,0x52);
输出,0xae,-82,82
有符号的整型负数在指定的格式转换中进行负数的补码原码转换。负数间接求补是负数,对一负数间接求补运算偶次得到原来的操作数。
29
负数的原码间接求补得到补码,补码 间接求补得到负数的原码。
正数 n的算术负运算或直接求补的结果就是负数 -n的补码。
例如,
1是正数,-1作为 4字节立即数存放的形式就是对正 1算术负运算作用的结果 0xffffffff,0xffffffff就是 -1的原始形态,
恰好是 -1的补码。对 0xffffffff间接求补得到 0x80000001,这是 -1的原码。
对 -1的原码的间接求补得到 -1的补码。
补码既可以当作是正数的算术负运算的结果,亦可视为是负数原码的间接求补。
30