Bootstrap

C++初学

逻辑运算真值表

位运算,位运算符,逻辑运算真值表
 
 
            A B A与B A或B 非A A异或B
            0 0  0    0    1    0
            0 1  0    1    1    1
            1 0  0    1    0    1
            1 1  1    1    0    0

              表 逻辑运算真值表
      其中
      0 代表错误(伪)
      1 代表正确(真)
以二进制为计算

C/C++基本数据类型:

Type

Size

数值范围

无值型void

0 byte

无值域

布尔型bool    

1 byte

true   false

有符号短整型short [int] /signed short [int]

2 byte

-32768~32767

无符号短整型unsigned short [int]  

2 byte

0~65535

有符号整型int /signed [int]

4 byte

-2147483648~2147483647

无符号整型unsigned [int]

4 byte

0~4294967295

有符号长整型long [int]/signed long [int]

4 byte

-2147483648~2147483647

无符号长整型unsigned long [int]

4 byte

0~4294967295

long long

8 byte

0~18446744073709552000

有符号字符型char/signed char

1 byte

-128~127

无符号字符型unsigned char

1 byte

0~255

宽字符型wchar_t (unsigned short.)

2 byte

0~65535

单精度浮点型float 

4 byte

-3.4E-38~3.4E+38

双精度浮点型double

8 byte

1.7E-308~1.7E+308

long double

8 byte

 

 

 

说明:

1)类型修饰符signedunsigned用于修饰字符型和整形。

2)类型修饰符shortlong用于修饰字符型和整形。

3)当用signedunsignedshortlong修饰int整形时,int可省略。

4)其中boolwchar_tC++特有的。

5)浮点数floatdouble的存储设计,从本质上来说是设计了一个数值映射,充分利用了2进制存储的特点。参考IEEE754浮点数表示标准。

6)除上表以外,C/C++都可以自定义枚举enum、联合unionstruct结构体类型。

7)以上sizeof通过Windows XP 32位平台测试,其中某些类型数据的字节数和数值范围由操作系统和编译平台决定。比如16位机上,sizeof(int) = 2,而32位机上sizeof(int) = 432位机上sizeof(long) = 4,而64位机上sizeof(long) = 8。除此之外,注意64位机上的pointer8byte

8void的字面意思是“无类型”,不能用来定义变量。void真正发挥的作用在于:<1> 对函数返回和函数参数的限定,例如自定义既不带参数也无返回值的函数void MyFunc(void);<2>定义无类型通用指针void *,指向任何类型的数据。

常量定义

(1)常量声明方法。

const 数据类型 常量标识符=表达式

(2)宏替换方法。

#define 宏名 表达式

数据转换

自动转换低向高转换。

 

例分析下面程序的输出结果 
#include<iostream.h>
void main()
{
      int a,b,m=3,n=4;
      a=7*2+-3%5-4/3;//-3%5=-3,4/3=1
      b=m++---n;
      cout<<a<<"/t"<<b<<"/t"<<m<<"/t"<<n<<endl;
}
执行结果如下:
      10043

(2)关系表达式
由关系运算符组成的表达式为关系表达式。关系表达式的运算结果为逻辑型,常用在条件语句和循环语句中。

例分析下面程序的执行结果
#include<iostream.h>
void main()
{
      char x='m',y='n';
      int n;
      n=x<y;
      cout<<n<<endl;
      n=x==y-1;
      cout<<n<<endl;
      n=('y'!='Y')+(5<3)+(y-x==1);
      cout<<n<<endl;
}
程序执行结果为:
      1
      1
      2

通过上面的程序可以看出:关系运算的结果为'真'时值等于1,结果为假时值等于0。
(3)逻辑表达式
由逻辑运算符组成的表达式称为逻辑表达式。逻辑表达式的值为逻辑型,结果为1和0。
在由&&和||运算符组成的逻辑表达式中,C++规定:只对能够确定整个表达式值所需要的最少数目的子表达式进行计算。也就是说,当计算出一个子表达式的之后便可确定整个逻辑表达式的值时,后面的子表达式就不需要再计算了,整个表达式的值就是该子表达式的值。这种表达式也称为短路表达式。参看例 

 
int a=3,b=0;问下面表达式运算后a和b的值是多少?
      (1)!a&&a+b&&a++
      (2)!a||a++||b++
分析:第一题是一个由&&组成的逻辑表达式,从左至右计算三个子表达式,只要有一个为0就不再计算其他子表达式。当计算!a的值为0时,便可确定整个表达式的值为0,因此后面的子表达式就不再计算了。所以a的值为3,b的值为0。
第二题:这是一个由||组成的逻辑表达式,从左至右计算三个子表达式,只要有一个结果为真则不再计算后面的子表达式。第一个子表达式为!a结果为0,再计算a++结果为4,所以就不再计算后面的子表达式。所以结果a为4,b为0。

(4)条件表达式
由三目运算符?:组成的表达式为条件表达式。例如a>b?x=4:x=9;条件表达式的值取决于?前面的表达式的值,该表达式的值为非0时,整个表达式的值为':'前面的表达式的值,否则为':'后面的表达式的值。

例分析下面程序的执行结果 
#include<iostream.h>
void main()
{      
      int a=3,b=4,c;
      c=a>b?++a:++b;
      cout<<a<<","<<b<<","<<c<<endl;
      c=a-b?a-3?b:b-a:a;
      cout<<a<<","<<b<<","<<c<<endl;
}
该程序执行的结果为:
      355
      352

(5)赋值表达式
由赋值运算符组成的表达式为赋值表达式。赋值运算符除了"="之外还有十个符合运算符,这是赋值和运算相结合的运算符。。
赋值运算符的结合性是由右至左,因此,C++程序中允许出现连赋值的情况。

例如下面的赋值是合法的。
      int a,b,c,d;
      a=b=c=d=5/2;
这里先计算5/2结果为2,再赋值给d,结果d=5/2表达式的值为2,再将这个值赋给c,以此类推,结果a、b、c、d的值均为2。
再计算复合赋值运算符表达式中,首先计算右值表达式的值后再与左值运算。例如:
      int a=3,b=4;
      a*=b+1;
这里先计算b+1等于5,再与a相乘赋值给a,结果等于15。
赋值还可以嵌入到比较运算表达式中,例如:
      x=func();
      if(x==3)
      {
      .....
      }
可以将赋值放在if的条件表达式中,如:
      if((x=func())==3)
      {...
      }
这里,比较运算符==的优先级高于赋值运算符,所以应将赋值运算加上括号。

(6)逗号表达式
逗号表达式是用逗号将若干个表达式连起来组成的表达式。该表达式的值是组成逗号表达式的若干个表达式中的最后一个表达式的值,类型也是最后一个表达式的类型。
逗号表达式的计算顺序是自左至右。

 

 

∷作用域运算符
      new动态分配内存单元运算符
      delete删除动态分配的内存单元运算符
      ·*和→*成员指针选择运算符
C++语言中的运算符是可以让C++语言编译器能够识别的具有运算意义的符号。编译器把这些符号及其组成的表达式翻译成相应的机器代码,就可以由计算机运行得出正确的结果。其实,就象我们日常生活当中许多东西的名字,如冰箱、电视机等分别代表不同功能的电器设备一样,运算符就是代表C++语言中的各个运算功能的名字,这些名字是由制定C++语言规范的人员确定的。下面给出由运算符组成的表达式的例子:
下面是几个表达式例子。如:
      100+200-300*200+1000/20+100%10
      a||b&&c||d
      a=b+c+d*e
      a+=b++
      c-=d--
只要是按C++语法写出的表达式,编译器就能够解释其中的运算符和由运算符、操作数组成的表达式的意义。
C++提供的运算符有以下几种:算术运算符、关系运算符、逻辑运算符、位运算符、条件运算符、赋值运算符、逗号运算符、sizeof运算符及其它运算符(这是按功能分的)。不同的运算符,需要指定的操作数的个数并不相同。根据运算符需要的操作数的个数,可将其分为三种:单目运算符(一个操作数)、双目运算符(两个个操作数)和三目运算符(三个操作数)。下面,我们介绍几种基本的C++运算符。
算术运算符
C++提供5种基本的算术运算符,参见表1。

表1    5种基本的算术运算符
运算符名字实例
+12+4.9//得出16.9
-3.98-4//得出-0.02
*2*3.4//得出6.8
/9/2.0//得出4.5
%取余13%3//得出1
这5个算术运算符都是双目运算符。除%运算符外,其它算术运算符的两个操作数可以是整型(shortint、int、longint、unsignedshortint、unsignedint或unsignedlongint型)和实型(float或double型)的混合类型,运算结果的数据类型是:两个操作数的数据类型中,具有较高级别的数据类型。例如,一个int型操作数和一个float型操作数的运算结果是float型;一个float型操作数和一个double型操作数的运算结果是double型。
当除运算符(/)的两个操作数均为整数时,所得的结果总是被圆整化为整数。例如:
      9/2//得出4,不是4.5!
      -9/2//得出-5,不是-4!
在程序设计中,我们有时可以利用整数除法获得所需要的结果,但也容易产生错误。如果两个操作数是整数,要获得实数除法,我们应当将两个或任一个整型操作数强制转换为实型数,例如:
      int cost=100;
      int volume=80;
      double unitPrice=cost/(double)volume;//得出1.25
执行除法运算时,如果除数为零,程序运行时,会产生一个被零除的错误。
取余运算符(%)的两个操作数都必须是整型数,运算结果是整除后的余数。例如:
       13%3的结果是1。
算术运算的结果可能太大,而不能存储在一个指定的变量中,这种情形称之为溢出。例如:
      unsignedchark=10*92;//溢出:920>255
在进行除运算时,需要注意右操作数,即除数应为非零值,否则就会产生浮点运算错误。编程时,我们通常用if语句判别除数是否为0,例如:
      if(a!=0)//只有a不等于0时才执行下面的操作
            c=b/a;
'%'为取余运算符,用于把它前面的整数值或表达式除以其后面的整数值或表达式,结果为不能被后面的整数或表达式整除的最小整数,它后面的数值应该为大于1的正整数。如表中所示的"13%7",就表示13除以7余6。
上面所有的运算符都是双目运算符,左右操作数可以是数值,也可以是表达式。根据左右操作数类型的不同会产生不同的结果。如:9/4=2,而9/4.0=2.5、9.0/4=2.5、9.0/4.0=2.5。
但'%'运算符的左右操作数必须是整数,否则,会产生编译错误。
同时需要注意的是:加法和乘法运算有可能超过计算机能表示的最大数,产生溢出。如:1.e307*1.e307则会产生一个不确定数,即计算机不能表示的数。计算机表示的常用数据类型的取值范围可以见下表。
 
类型最小值最大值
signedchar-128+127
unsignedchar0+255
signedshort-32768+32767
unsignedshort0+65535
signedlong-2147483648+2147483647
unsignedlong0+4294967295
Float-3.402823466e
+38F
+3.402823466e
+38F
Double-1.7976931348
623158e+308
+1.7976931348
623158e+308
另外,整型的数值中有不同的类型如字符型、短整型、长整型。他们之间的类型转换需要特别的注意。如:
一个无符号字符型的变量
      unsignedchara,b;
      a=90*10;//结果a不等于900,而等于132,其实就是把900这个整数转化为无符号字符型数的结果,即(unsignedchar)900的结果为132。
      b=200+100;//结果b不等于300,而等于44。
它们之间的优先级关系是运算符'*''/''%'相同,且优先于运算符'+'、'-'。在搞不清优先级关系时,最好用括号'('')'进行分离组合。如:
(100.+20.)-(20-30)*40.
需要注意的是:当这些符号出现在字符串中时,就被计算机的编译器处理成字符串中的字符,而不是运算符。如:字符?quot;ab+cd-def"中的'+'和'0'就只是代表两个字符而已。而且,'+'、'-'运算符也可以作为单目运算符使用,如+100,-100分别表示正的100和负的100。当它们作为单目运算符时,将具有很高的运算优先级。具体可看3.2优先级和结合性一节。
自增、自减运算符
++是自增运算符,――自减运算符,这两个运算符都是单目运算符,且功能相近,都是将数值变量的值加1或减1,用户只能将这类操作符应用于变量而不能应用于常量。要替代下列代码
      valuel=valuel+1;
可使用
      ++valuel;

      valuel++;
这里前一种方式称为前缀方式,后一种称为后缀方式,其目的都是使valuel加1。二者的区别是:前缀式先将操作数增1(或减1),然后取操作数的新值参与表达式的运算。后缀是先将操作数增1(或减1)之前的值参与表达式的运算,到表达式的值被引用之后再做加1(或减1)运算。
我们可以看出,自加和自减运算符可在变量名前,也可在变量名后,即都可以用于前缀和后缀的形式,但含义并不相同。对于前缀的形式,变量先作自加或自减运算,然后将运算结果用于表达式中;而对于后缀的形式,变量的值先在表达式中参与运算,然后再作自加或自减运算。
可以作自加或自减的变量类型也可以是实型,但是,实型变量自加或自减运算的用处不大,我们很少使用。通常,我们对整型变量作自加或自减运算。以后,我们还会看到,指针变量也可以作自加或自减运算。
表2 自加和自减运算符
运算符名字实例
++自加(前缀)++valuel+10//得出16,valuel变为6
++自加(后缀)valuel+++10//得出15,valuel变为6
--自减(前缀)--valuel+10//得出14,valuel变为4
--自减(后缀)valuel--+10//得出15,valuel变为4
表中假定变量valuel已预定义:
      int valuel=5;
自加自减运算符都是单目运算符,是专门用于加1和减1操作设置的,其实质就是用'++'代替了"+1"(后缀)和"1+"(前缀)、'-'代替了"-1"。需要注意的是自增运算符在操作数的前面和后面是不一样的,如:
      a=6;
      b=a++;
执行结果为:b=6,a=7

      a=6;
      b=++a;
执行结果为:b=7,a=7.
自减运算符也存在同样情况,如:
      a=6;
      b=a--;
执行结果为:b=6,a=5.

      a=6;
      b=--a;
执行结果为:b=5,a=5.

关系运算符
C++提供6种关系运算符,用于数值之间的比较,表达式的值或为1(表示true),或为0(表示false),参见表3。

表3 关系运算符
运算符名字实例
==等于5==5//得出1
!=不等于5!=5//得出0
<小于5<5.5//得出1
<=小于或等于5<=5//得出1
>大于5>5.5//得出0
>=大于或等于6.3>=5//得出1

应该注意:<=和>=运算符不能写成=<和=>,=<和=>是无效的运算符。关系运算符的操作数应当是一个数值,字符是有效的操作数,因为它们是用数值来表示的。例如(假定采用ASCII编码):
      'A'<'F'//得出1(它等价于65<70)
字符串不应当用关系运算符比较,因为被比较的不是字符串的内容本身,而是字符串的地址。例如:
      "HELLO"<"BYE"
引起"HELLO"的地址与"BYE"的地址进行比较。由于字符串的地址是由编译器决定的,所以,表达式的结果或为0,或为1,并不确定。我们以后会看到:可以用C++的库函数strcmp,比较两个字符串。  由关系运算符组成的关系表达式的值是逻辑型的,即bool型。在C++中常常将逻辑真用非0表示(一般为1),逻辑假用0表示。
其中:
·'=='用于判断其前后数值或表达式的结果a和b是否相等。如a为2001,b为667*3,则表示a等于b是真的。
·'!='用于判断其前后数值或表达式的结果a和b是否不相等。如a为2002,b为667*3,则表示a不等于b是真的。
·'<'用于判断其前后数值或表达式的结果a是否小于b。如a为2002,b为667*3,则表示a小于b是假的。
·'<='用于判断其前后数值或表达式的结果a是否小于或等于b。如a为2002,b为667*3,则表示a小于或等于b是假的。
·'>'用于判断其前后数值或表达式的结果a是否大于b。如a为2002,b为667*3,则表示a大于b是真的。
·'>='用于判断其前后数值或表达式的结果a是否大于或等于b。如a为2002,b为667*3,则表示a大于或等于b是真的。
关系运算符组成的表达式,一般是和逻辑运算符组合用在条件表达式中的。条件表达式用于程序的分支处理。
注意
1.关系运算符两边的数值结果必须是类型相同的,否则会容易出现关系判断的错误。如:
      char a='0xa2';
a>'0xa1'的结果是a小于'0xa1'。因为a是符号整数,而'0xa1'是无符号整数。给a赋值后其实是小于0的。
2.字符串不应当用关系运算符比较,因为被比较的不是字符串的内容本身,而是字符串的地址。例如:
      "Welcome"<"Beijing"
引起"Welcome"的地址与"Beijing"的地址进行比较。由于字符串的地址是由编译器决定的,所以,表达式的结果或为假,或为真,并不确定。我们以后会看到:可以用C++的库函数strcmp,比较两个字符串。

表达式的种类
表达式是由运算符和操作数组成的式子。运算符可以是前面讲过的那些。操作数包含了常量、变量、函数和其他一些命名的标识符。最见大的表达式是常量和变量。
C++中由于运算符很丰富,因此表达式的种类也很多。常见的表达式有如下六种:
已知int a;
·· 算术表达式。例如,a+5.2/3.0-9%5
·· 关系表达式。例如,'m'>='x'
·· 逻辑表达式。例如,!a&&8||7
·· 条件表达式。例如,a>4?++a:--a
·· 赋值表达式。例如,a=7
·· 逗号表达式。例如,a+5,a=7,a+=4
注意:
1、在表达式中,连续出现两个运算符时,最好用空格符分隔。如:
      a+++b;(注意:在visualc++中这种写法是错误的,编译将不能通过)
系统将默认为是a+++b,因系统将按尽量取大的原则来分割多个运算符。如果想执行a加++b,则应写成
      a+++b;
2、在写表达式中,有时记不清楚运算符的优先级时,可使用括号来确定运算符组合。

表达式的值和类型
任何表达式经过计算都应有一个确定的值和类型。在计算一个表达式的值时,应注意下述两点:
1、先确定运算符的功能。在C++中,有些运算符相同但功能不同,因此要先确定其功能。例如运算符:*,&,-。它们有时是单目运算符,有时是双目运算符,在计算前要分清楚。
2、确定计算顺序。
一个表达式的计算顺序是由运算符的优先级和结合性来决定的。优先级高的先做,优先级地的后做。在优先级相同的情况下,右结合性决定。多数情况下,由左至右。少数情况下,由右至左。
表达式的类型由运算符的种类和操作符的类型决定。
表达式的求值方法和确定类型的方法如下:
(1)算术表达式
算术表达式是由算术运算符和位操作运算符组成的表达式,其表达式的值是一个数值。表达式的类型具体地由运算符合操作数决定

例 分析下面程序的执行结果
#include<iostream.h>
void main()
{
      int a,b,c;
      a=1,b=2,c=a+b+3;
      cout<<a<<','<<b<<','<<c<<endl;
      c=(a++,a+=b,a-b);
      cout<<a<<','<<b<<','<<c<<endl;
}
输出结果如下:
      1,2,6
      4,2,2


 

表1    5种基本的算术运算符
运算符名字实例
+12+4.9//得出16.9
-3.98-4//得出-0.02
*2*3.4//得出6.8
/9/2.0//得出4.5
%取余13%3//得出1

;