首页 理论教育 C51运算与构造数据类型实战

C51运算与构造数据类型实战

时间:2023-11-06 理论教育 版权反馈
【摘要】:如果赋值运算符号两边的数据类型不一致,则系统将自动进行类型转换。其作用就是对运算对象作加1和减1运算。C51中共有6种位运算符。2)C51的构造数据类型数组数组就是一组具有相同数据类型的数的有序集合。其特点是数组中的数必须是同一种类型,这些数必须按照一定次序存放,数组的下标表示数的存放次序。C语言规定只能逐个引用数组元素,而不能一次引用整个数组。

C51运算与构造数据类型实战

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。

(10)指针地址运算符

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等。

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈