1)运算符
运算符是完成某种特定运算的符号。运算符按其表达式中运算对象与运算符的关系可分为单目运算符、双目运算符和三目运算符。单目要求有一个运算对象,双目要求有两个运算对象,三目则要求有3个运算对象。表达式是由运算及运算对象所组成的具有特定含义的式子。
(1)赋值运算符
赋值语句格式如下:
变量=表达式;
例如:
由上面的例子可以看出,赋值语句的意义就是先计算出“=”右边表达式的值,然后将得到的值赋给左边的变量,而且右边的表达式也可以是一个赋值表达式。如果赋值运算符号两边的数据类型不一致,则系统将自动进行类型转换。转换方法是把赋值符号右边的类型转换成左边的类型,具体规定如下:
①实型赋给整型:舍去小数部分。
②整型赋给实型:数值不变,必须以浮点形式存放(增加小数部分,小数部分的值为0)。
③字符型赋给整型:因为字符型为一个字节,整型为两个字节,因此需将字符的ASCII码值放到整型量的低八位中,高八位补0。
④整型赋给字符型:只把低八位赋给字符量。
(2)算术运算符
C51的算术运算符如下:
+ 加或取正值运算符 - 减或取负值运算符
* 乘运算符 / 除运算符 % 取余运算符
其中,只有取正值和取负值运算符是单目运算符,其他都是双目运算符。注意在除法运算中,如果两个浮点数相除,其结果为浮点数,如8.0/4.0=2.0,而两个整数相除,结果为整数,如8/3=2。
算术表达式的形式如下:
表达式1 算术运算符 表达式2
例如:a+b*(10-a),(x+9)/(y-a)。
(3)关系运算符
对于关系运算符,在C中有6种关系运算符:>(大于),<(小于),>=(大于等于),<=(小于等于),==(等于),!=(不等于)。
在关系运算中,关系运算符的优先级别为:前四个具有相同的优先级,后两个也具有相同的优先级,但是前四个的优先级高于后两个。关系运算的结果只有“0”和“1”两种,即逻辑的真和假。
关系表达式的形式如下:
表达式1关系运算符表达式2
例如:(I=4)<(J+1)。
(4)逻辑运算符
逻辑运算符有3个:&&(逻辑与),||(逻辑或),!(逻辑非)。
逻辑运算符是对逻辑量运算的表达,结果要么是真(非0),要么是假(0)。
逻辑表达式的一般形式如下:
逻辑与:条件式1 &&条件式2。
逻辑或:条件式1||条件式2。
逻辑非:!条件式2。
逻辑运算符也有优先级别:!(逻辑非)→&&(逻辑与)→||(逻辑或),逻辑非的优先值最高。
(5)++(增量运算符)和--(减量运算符)
这两个运算符是C语言中特有的一种运算符。其作用就是对运算对象作加1和减1运算。要注意的是:运算对象在符号前和符号后,其含义都是不同的。
①i++(或i--)的含义是先使用i的值,再执行i+1(或i-1)。
②++i(或--i)的含义是先执行i+1(或i-1),再使用i的值。
(6)位运算符
位运算符的作用是按位对变量进行运算,但是并不改变参与运算的变量的值。如果要求按位改变变量的值,则要利用相应的赋值运算。注意:位运算符是不能用来对浮点型数据进行操作的。C51中共有6种位运算符。
位运算的一般表达形式如下:
变量1位 运算符 变量2
位运算符也有优先级,从高到低依次是:~(按位取反)→<<(左移)→>>(右移)→&(按位与)→^(按位异或)→|(按位或)。
(7)复合赋值运算符
复合赋值运算符就是在赋值运算符“=”的前面加上其他运算符。C语言中的复合赋值运算符:+=加法赋值,-=减法赋值,×=乘法赋值,/=除法赋值,%=取模赋值,&=逻辑与赋值,|=逻辑或赋值,^=逻辑异或赋值,-=逻辑非赋值,<<=左移位赋值,>>=右移位赋值。
复合运算的一般形式如下:
变量复合赋值运算符表达式
例如:a+=56等价于a=a+56,y/=x+9等价于y=y/(x+9)。
(8)逗号运算符
C语言中逗号是一种特殊的运算符,可以用它将两个或多个表达式连接起来,形成逗号表达式。
逗号表达式的一般形式如下:
表达式1,表达式2,表达式3,…,表达式n
逗号运算符组成的表达式在程序运行时,从左到右计算出各个表达式的值,而整个用逗号运算符组成的表达式的值等于最右边表达式的值,即“表达式n”的值。例如:
程序的结果为:n=11,m=7。
(9)条件运算符
C语言中有一个三目运算符,即“?:”条件运算符,它要求有3个运算对象。
条件表达式的一般形式如下:
逻辑表达式?表达式1:表达式2
条件运算符的作用就是根据逻辑表达式的值选择使用表达式的值。当逻辑表达式的值为真(非0值)时,整个表达式的值为表达式1的值;当逻辑表达式的值为假(值为0)时,整个表达式的值为表达式2的值。例如,min=(a<b)?a:b,如果a<b成立,min=a,否则,m=b。
C语言中提供了两个专门用于指针和地址的运算符:
①*:取内容。
②&:取地址。
取内容和地址的一般形式如下:
变量=*指针变量
指针变量=&目标变量
取内容运算是将指针变量所指向的目标变量的值赋予左边的变量;取地址运算是把目标变量的地址赋予左边的变量。
2)C51的构造数据类型
(1)数组
数组就是一组具有相同数据类型的数的有序集合。其特点是数组中的数必须是同一种类型,这些数必须按照一定次序存放,数组的下标表示数的存放次序。数组可分为一维、二维、三维和多维数组。
例如,数组a[10]的元数分别是:
a[0],a[1],a[2],…,a[9]。
①一维数组。一维数组的定义方式如下:
数据类型 数组名[常量表达式];
数据类型说明数组中各个元素的类型;数组名是整个数组的标识符,它的定名方法与变量一样;常量表达式说明了该数组的长度,必须用[]括起来,且不能含有变量。
数组必须先定义,后使用。C语言规定只能逐个引用数组元素,而不能一次引用整个数组。
一维数组在计算机内是怎样存储的呢?在编译时,系统根据数组的定义为数组分配一个连续的存储区域,数组中的元素按照下标由小到大的次序连续存放,下标为0的元素排在前面,每个元素占据的存储空间大小与同类型的简单变量相同。例如:(www.xing528.com)
int a[5];
数组a中每个元素在内存中占2个字节的存储空间,其示意图如下:
对数组进行如下初始化:
将各数组元素的初值写在花括号中,用逗号隔开,并从数组的0号元素开始依次赋值给数组的各个元素。例如,int a[10]={0,1,2,3,4,5,6,7,8,9},经过定义和初始化之后,a[0]=0,a[1]=1,a[2]=2,a[3]=3,a[4]=4,a[5]=5,a[6]=6,a[7]=7,a[8]=8,a[9]=9。
②二维数组。二维数组的定义方式如下:
类型说明符 数组名[常量表达式1][常量表达式2];
例如:
int a[3][4],b[5][5];
定义a为3×4(3行4列)的数组,b为5×5(5行5列)的数组。注意不要写成:
int a[3,4],b[5,5];
在C语言中,可以把二维数组看成一种特殊的一维数组,它的元素是一个一维数组。例如,int a[3][4],可以把a看作一个一维数组,它有3个元素a[0]、a[1]、a[2],每个元素又是一个包含4个元素的一维数组,即
在内存中,二维数组元素的存放顺序是按行存放,即在内存中先顺序存放第一行的元素,再存放第二行的元素,依次类推。例如,int a[3][4],数组a中每个元素在内存中占2个字节的存储空间,其示意图如下:
③字符数组。字符数组的定义和其他数组的定义相类似。类型说明符为char。
三维数组的定义方式如下:
char 数组名[下标];
例如:
char b[10];
b[0]=‘T’;b[1]=‘h’;b[2]=‘a’;b[3]=‘n’;b[4]=‘k’;b[5]=‘’;b[6]=‘y’;b[7]=‘o’;b[8]=‘u’;b[9]=‘!’;
此例中用赋值语句给字符数组赋初值。
字符数组的每一个元素只能存放一个字符(包括转义字符)。数组在内存中的存储状态如下:
字符是以ASCII码的形式存储在内存中的,字符数组的任一元素相当于一个字符变量。
在C语言中,不提供字符串数据类型,字符串是存放在字符数组中的。C语言规定:以“\0”作为字符串结束标志。因此,在用字符数组存放字符串时,系统自动在最后一个字符后加上结束标志“\0”,表示字符串到此结束。因此,在定义字符数组时,数组长度至少要比字符串中字符个数多1,以便保存字符“\0”。
查表是数组的一个常用的功能。例如,摄氏温度转换成华氏温度:
(2)指针
指针变量的定义与一般变量的定义类似,其形式如下:
数据类型[存储器类型1]*[存储器类型2]标识符;
[存储器类型1]表示被定义为基于存储器的指针,无此选项时,被定义为一般指针。这两种指针的区别在于其存储字节不同。一般指针在内存中占用3个字节,第一个字节存放该指针存储器类型的编码(在编译时由编译模式的默认值确定),第二和第三字节分别存放该指针的高位和低位地址偏移量。
[存储器类型2]用于指定指针本身的存储器空间。存储器类型的编码值如下:
C51支持一般指针和存储器指针。
①一般指针。一般指针的声明和标准C一样,不过声明的同时可以说明指针的存储类型。例如:
long*state; //指向long型整数的指针,而state本身依存储模式存放
char*xdata ptr;//指向char型数据的指针,而ptr本身存放于外部RAM
上述定义的是一般指针,ptr指向的是一个char型变量,char型变量所在的区域和编译时编译模式的默认值有关,如果是Memory Model—Variable—Large:XDATA,那么这个char型变量位于xdata区;如果是Memory Model—Variable—Compact:PDATA,那么这个char型变量位于pdata区;如果是Memory Model—Variable—Small:DATA,那么这个char型变量位于data区。指针state变量本身位于片内数据存储区中。
②存储器指针。存储器指针在说明时就指定了存储类型。例如:
char data*str;//str指向data区中的char型数据
int xdata*p;//p指向外部RAM的int型整数
这种指针存放时,因为只需要存放偏移量,所以只需要1或2个字节。
下面介绍指针与数组存在的关系。例如:
{int arr[10];int*pr;pr=arr;}
由于pr=arr等价于pr=&arr[0],那么就有*(pr+1)==arr[1],*(pr+2)==arr[2],*(arr+3)==arr[3],*(arr+4)==arr[4],或者pr[0],pr[1],…代表arr[0],arr[1],…。
可以用*pr++(等价于*(pr++))来访问所有数组元素,而用*arr++是不行的。因为arr是常量,所以不能进行++运算。
下面介绍指针的应用。指针变量的初始化如下:
(3)结构体
因为结构体类型描述的是类型不相同的数据,所以其描述无法像数组一样统一进行,只能对各数据成员逐一进行描述。结构体类型定义用关键字struct标识。定义一个结构体的一般形式如下:
struct结构名
{结构元素列表};
其中,结构名是结构体类型名的主体,定义的结构体类型由“struct结构名”标识;结构元素列表又称域表、字段表,由若干个结构元素组成,每个结构元素都是该结构的一个组成部分。对每个结构元素也必须作类型说明,其形式如下:
类型说明符 结构元素名
例如,定义一个student的结构体:
注意:结构元素名的命名应符合标识符的书写规定。
①结构体变量的定义。结构体变量的定义是在结构体定义之后加上变量名。例如:
如果结构体变量超过3个,则采用数组的形式,比如stu[5]。
②结构体变量的初始化。当结构体变量为全局变量或静态变量时,可以在定义结构体类型时给它赋值,但不能够给自动存储种类的动态局部结构变量赋值。例如:
自动结构变量不能在定义时赋初值,只能在程序中用赋值语句为各结构元素分别赋值。结构体变量初值的个数必须小于或等于结构体变量中元素的个数。
③结构体变量的引用。结构体变量的引用是通过所属的结构元素的引用来实现的。其形式如下:
结构体变量名.结构元素
例如,stu1.score=(stu2.score+stu3.score)/2。
④结构型指针。定义结构型指针的形式如下:
struct结构类型标识符 *结构指针标识符
其中,结构指针标识符是所定义的结构型指针变量的名字,结构类型标识符是该指针所指向的结构变量的具体名称。例如:
struct mepoint *mp;
用结构型指针可以引用结构元素,形式如下:
结构指针→结构元素
例如,mp->pressure等价于(*mp).pressure。
指针和结构体有什么关系呢?现通过一个例子来介绍指针和结构体的关系。例如:
开辟一个外RAM空间,确保这个空间足够容纳所需要的内容,程序如下:
此时,结构体指针指向这个数组的开头,操作如下:
操作后变量就位于XDATA中了。注意:定义的my_data[MAX_STR]不能随便被操作,它只是开始的时候用来开辟内存的。
(4)共用体
共用体与结构体的定义相类似,只是定义时把关键词struct换成union。共用体类型变量的定义形式如下:
①共用体变量的定义。共用体变量的定义为在共用体定义后面直接给出的变量。例如:
②共用体变量的引用。共用体变量的引用形式如下:
共用体变量名.共用体元素
例如:data1.i、data2.ch、data3.f等。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。