一、寄存器
1. 寄存器概述
- 运算器
- 控制器
- 总线:内部总线实现CPU内部各个器件之间的联系;外部总线实现CPU和主板上其它器件的联系。
2. 通用寄存器
(1)AX、BX、CX、DX 通常用来存放一般性数据,被称 为通用寄存器。
- AX可以分为AH和AL;
- BX可以分为BH和BL;
- CX可以分为CH和CL;
- DX可以分为DH和DL。
- 字的低位字节 保存在 寄存器的低8位寄存器
- 字的高位字节 保存在 寄存器的高8位寄存器
此时CPU把 al 和 ah 看作8位的寄存器上的独立的寄 存器,低8位上加法产生的进位不会存储在ah中。
3. 物理地址
8086CPU采用一种在内部用两个16位地址合成的方法来形成一个20位的地址。方法是:物理地址=段地址×16+偏移地址
4. 段
(2)段的起始地址一定是16的倍数。一个段的长度最大是64K,因为偏移地址是16位。
5. 代码段
(1)8086CPU有4个段寄存器: CS 、DS 、SS 、ES。当8086CPU要访问内存时,这些段 寄存器提供内存单元的段地址。
(2)CS(Code Segment 代码段寄存器)和 IP(Instruction Pointer 指令指针寄存器)是8086CPU中最关键的寄 存器,它们指示了CPU当前要读取指令的指令地址。IP寄存器自动累加,指向下一条指令的内存的偏移地址
- 从CS:IP指向内存单元读取指令, 读取的指令进入指令缓冲器
- IP = IP + 所读取指令的长度,从 而指向下一条指令
- 执行指令。 转到步骤1,重复这 个过程
(4)因为电启动或复位后CPU默认自动设置 :CS=FFFFH ,IP=0000H 。所以CPU从内存FFFF0H单元中读取指令执行,这是 开机后执行的第一条指令。
(5)不能通过mov 指令改变CS、IP的值,应使用转移指令(jmp)指令改变CS、IP的值。
- jmp 段地址: 偏移地址 功能:用指令中的段地址修改CS,偏移地址修改IP。
- jmp 某一合法寄存器功能:用寄存器的值修改 IP.
- 内存中指令和数据没有任何区别,都是二进制信息,CPU在工作的时候把有的信息看作指令,有的信息看作数据。
- CPU根据什么将内存中的信息看作指令?CPU将CS:IP指向的内存单元中的内容看作指令。
6. 数据段
(1)数据段的段地址寄存器:DS(Date Segment)
(2)可将一组长度为N(N≤64K)、地址连续、起始地址为16的倍数的内存单元当作专门存储数据的内存空间——数据段。
(3)mov指令读取内存的格式: mov 寄存器名,[address] 。其中address为内存单元的偏移地址。此指令需要用DS中数据作为内存单元的段地址,所以一定要保证DS已保存正确的段地址。
(4)8086CPU不支持将数据直接送入段寄存器的操作,只支持数据→通用寄存器→段寄存器。
7. 栈段
(1)8086CPU中,SS:SP指向栈顶元素: SS 段寄存器,存放栈顶的段地址 ;SP 寄存器,存放栈顶的偏移地址。
(2)8086PC机编程时,程序员可将起始地址为16的倍数一组连续的长度为 N(N ≤64K )的内存单元定义为一个段——用作栈时,即为一个栈段。
三、汇编语言程序
1. 源程序
- 编写
- 编译:使用汇编语言编译程序对源程序进行编译,产生目标文件
- 连接:用连接程序将目标文件连接成可执行文件
- 执行
没有对应机器码的指令,最终不被CPU 所执行。 谁来执行伪指令呢?伪指令是由编译器来执行的 指令,编译器根据伪指令来进行相关的编译工作。
2. 连接
(1)连接多个文件:大源程序可分为多个小源程序,每个源程序可独立编译成一个目标文件,将它们连接生成一个可执行文件。
(2)连接库文件:程序中调用某个库文件中的子程序时,将这个库文件和该子程序的目标文件连接到一起,生成一个可执行文件。
3. [BX]和loop指令
[bx] 表示一个内存单元:偏移地址在bx中, 段地址在ds中 ,单位(长度)由另外一个操作数指出。
标号:循环部分的代码
…
loop 标号
4. 更灵活的定位内存方法
在8086CPU 中,只有这4个寄存器(bx、bp、si、di)可以用在“[…]” 中来进行内存单元的寻址。
[bx+idata] 这种访存方式便于使用更高级的结构来看待所要处理的数据。
还可以用 [si / di] 或 [si / di + idata] 或 [bx + si / di] 来指明一个内存单元
(3)[bx+si+idata] 和 [bx+di+idata]
(4)这分别对应着不同的寻址方式,bx 是基址寄存器,si 和 di 是变址寄存器
- [idata]:用一个常量表示内存地址,直接寻址
- [bx]:用一个变量表示内存地址,间接寻址
- [bx + idata]:一个变量和常量表示地址,寄存器相对寻址
- [bx + si]:两个变量表示地址,基址变址寻址
- [bx + si + idata]
只要在[…]中使用寄存器bp,而指令中没有显性的给出段地址,则段地址默认在ss中。
只要在[…]中使用寄存器bx,而指令中没有显性的给出段地址,则段地址默认在ds中。
5. 跳转指令
- 跳转目的地址为标号(立即数)
- jmp short 标号:实现段内短转移,IP的修改范围是8位。
- jmp near ptr 标号:段内近转移。IP的修改范围是16位。
- jmp far ptr 标号:段间转移,CS修改为标号所在段中的段地址(绝对地址),IP修改为标号所在段的偏移地址。
- 跳转目的地址在寄存器中
- jcxz指令为有条件转移指令,所有的有条件转移指令都是短转移,在对应的机器码中包含转移的位移,而不是目的地址。对IP的修改范围都为-128~127。
- 格式 jcxz 标号,如果 (cx) = 0,则转移到标号处执行。否则,程序向下执行。相当于 if((cx)==0) jmp short 标号;
- loop指令为循环指令,所有的循环指令都是短转移,在对应的机器码中包含转移的位移,而不是目的地址。对IP的修改范围都为-128~127。
- loop指令操作:
- 如果 (cx)≠0,(IP)=(IP)+8位位偏移。
- 这些指令对 IP的修改是根据转移目的地址和当前之间的位移来进行——此位移信息包含在机器码中。
- 根据位移进行转移时,转移位移受到移范围受到的限制,否则编译器将报错。
6. call 和 ret 指令
ret 指令
(1)(IP)=((ss)*16+(sp))
(1)(IP)=((ss)*16+(sp))
(2)(sp)=(sp)+2
(3)(CS)=((ss)*16+(sp))
CPU执行retf指令时,相当于进行:pop IP pop CS
call 指令
- 压栈:将 IP 或(CS 和 IP) 入栈;
- 转移: 相对或绝对位置转移。
call 指令不能实现短转移(8位长的位移),除此之外,call指令实现转移的方法和 jmp 指令的原理相同。
功能:相对转移——先将IP压栈,再通过位移转到标号处执行指令
(1) (sp) = (sp) – 2
((ss)*16+(sp)) = (IP)
push IP
(1) (sp) = (sp) – 2
((ss) ×16+(sp)) = (CS)
(sp) = (sp) – 2
((ss) ×16+(sp)) = (IP)
(2) (CS) = 标号所在的段地址
push CS
push IP
(1)(sp) = (sp) – 2
((ss)*16+(sp)) = (IP)
push IP
push IP
push CS
push IP
7. div指令
8. mul指令
四、标志寄存器
0. 概述
(1)8086CPU的标志寄存器有16位~ 程序状态字(PSW)
标志位表示一些指令执行的结果:OF、DF、IF、TF、SF、ZF、AF、PF、CF
- flag寄存器是按位起作用的
- 其他寄存器是整个寄存器具有一个含义
1. ZF标志
- 若结果为0 ,则ZF = 1 (~真)
- 若结果非0, 则ZF = 0 (~假)
2. PF标志
(1)PF (Parity flag),奇偶标志位。 它记录指令执行后,结果最后一个字节(LSB)的二 进制位中1的个数:
- 为偶数,PF = 1
- 为奇数,PF = 0
3. SF标志
(1)SF (sign flag),符号标志位。 它记录指令执行后,
- 结果为负,SF = 1
- 结果为非负,SF = 0
(2)CPU在执行 add 等指令时,无论数据本身是有符号 数或者无符号数,CPU按照总会有符号数加法结果 来设影响到SF标志位的值的。
- 对于有符号数,可以通过SF来得知结果的正负
- 对于无符号数,则SF的值则没有意义
4. CF标志
在进行无符号数加法(减法)运算的时候,它记录了运算结果的最高有效位向(从)更高位的进位(借位)值
5. OF标志
溢出问题:在进行有符号数运算的时候,若结果超 过了机器所能表示的范围称为溢出。
- 如果发生溢出,OF=1
- 如果没有溢出,OF=0
6. adc指令 ( add with carry flag )
- 比如: adc ax,bx
- 实现的功能: (ax)=(ax) + (bx) + CF
7. sbb指令 ( subtract with borrow flag )
- 如:sbb ax,bx
- 实现功能: (ax) = (ax) - (bx) - CF
8. cmp指令
- 格式:cmp 操作对象1,操作对象2
- 功能:计算操作对象1 - 操作对象2 ,根据计算结 果设置标志寄存器。
因 (ax) - (ax) 的等于0,修改 flag 的相关位:
9. 检测比较结果的条件转移指令
- 根据无符号数的比较结果进行转移的条件转移指令,它们检测ZF、CF的值;
- 根据有符号数的比较结果进行转移的条件转移指令,它们检测 SF、OF和 ZF的值。
10. DF标志和串传送指令
- DF = 0:每次操作后si,di递增
- DF = 1:每次操作后si,di递减
- cld指令( clear direction flag):设置DF为0
- std指令( set direction flag) :设置DF为1
movsb 功能:以字节为单位传送,即将 ds:si 指向的内存单元中的字节送入 es:di中,然后根据标志寄存器DF位的值,将 si和di递增或递减1。
(1) ((es)×16 + (di)) byte= ((ds) ×16 + (si)) byte
(2) 如果DF = 0则:(si) = (si) + 1
(di) = (di) + 1
如果DF = 1则:(si) = (si) - 1
movsw 功能:以字为单位传送,即将 ds:si指向的内存字单元中送入es:di中,然后根据标志寄存器DF位的值,将si和di递增2或递减2。
(1) ((es)×16 + (di)) word= ((ds) ×16 + (si)) word
(2) 如果DF = 0 则:(si) = (si) + 2
(di) = (di) + 2
如果DF = 1 则:(si) = (si) - 2
(3)movsb 和 movsw 进行的是串传送操作中的一个步骤,它们 rep 配合使用:
rep的作用:根据cx值,重复执行后面的串传送指令。每执行一次movsb指令si和di都会递增或递减,从而指向后一个或前一个单元,则rep movsb就可以循环实现(cx)个字符的传送。
11. pushf 和 popf
pushf 和 popf为直接访问标志寄存器提供了一种方法。
五、中断
1. 内中断
1.1 概述
中断:CPU不接着向下执行,而转去处理特殊信息(中断信息)。
中断向量表:内存中存放中断源所对应的中断处理程序的入口地址(中断向量)。
(2)按中断向量设置CS和IP ,CPU执行中断过程(因为中断处理完后需要返回到原执行点继续执行,所以先保存当前 CS和IP值)。
1.2 中断处理程序
- 中断处理程序必须一直存储在内存中
- 中断处理程序中断向量必须存储在对应的中断向量表表项中
(1)保存用到的寄存器。
(2)处理中断。
(3)恢复用到的寄存器。
1.3 iret指令
功能:从栈依次弹出 IP、CS、标志寄存器,恢复执行中断处理程序前的CPU现场,并继续执行程序。
pop IP
pop CS
1.4 除法错误中断的处理
(1)产生中断信息:中断类型码为 0
(2)CPU检测到中断信息
(3)引发中断过程
第1步:实现预期功能的中断程序
第2步:安装程序-将程序放在常驻内存空间
程序分为4部分:do0安装程序;设置中断向量表;返回操作系统;do0+返回操作系统
此程序加载到内存,然后复制 do0 到 0:2022,接着设置中断向量。
- do0 安装程序:使用 movsb 指令,将 do0 的代码送入 0000:0200 处
- 设置中断向量:将 do0 的入口地址 0:200 写入中断向量表 0 号表项中
1.5 单步中断(1号中断)
CPU在执行完一条指令之后,如果检测到标志寄存器的TF位为1,则产生单步中断,引发中断过程。
单步中断的一个典型的应用就是在Debug中的应用了。单步执行后会显示个寄存器的值以及下一条将要执行的指令。方便程序员的调试工作。
(1)取得中断类型码1;
(2)标志寄存器入栈,TF、IF设置为0;
(3) CS、IP入栈;
注意这里第(2)步中TF设为0。假若设为1,CPU在执行完中断处理程序的第一条指令后又要产生单步中断,最后导致中断调用的死循环
2. int 指令
取中断类型码 n
标志寄存器入栈, IF = 0 , TF = 0
CS 、 IP 入栈
(IP) = (n*4) , (CS) = (n*4+2) 。
2.1 BIOS 和 DOS 所提供的中断例程
(1)BIOS ( Basic Input Output System )在主板 ROM
- 硬件系统的检测和初始化程序
- 外部中断和内部中断的中断例程
- 用于对硬件设备进行 I/O 操作的中断例程
- 其他和硬件系统相关的中断例程
(2)DOS 提供了中断例程,即提供给程序员的编程资源。程序员用 int 调用 BIOS 和 DOS 的中断例程。
(3)BIOS 和 DOS 的中断例程是如何安装到内存中的呢
- 开机后 CPU 初始化 (CS)=0FFFFH , (IP)=0 ,从 FFFF:0 处开始执行第一条指令,该指令为一条转跳指令。
- CPU 转去执行 BIOS 中的硬件系统检测硬件系统检测和初始化程序初始化程序(将 BIOS 的中断例程的入口地址登记在中断向量表中)。
- 硬件系统检测和初始化完成后,调用 int 19h 进行操作系统的引导。从此将计算机交由操作系统操作系统控制。
- DOS 启动后,除完成其它工作外,还将它所提供的中断例程装入内存,并建立相应的中断向量。
- 中断例程包括多个子程序时,用传递的参数来决定 执行哪个子程序。
- BIOS 和 DOS 提供的中断例程,都用 ah 来传递内部子程序的编号。
3. 外中断
3.1 接口芯片和端口
(1)PC 系统的主板和接口卡上装有各种接口芯片 , 接口芯片的内部有若干寄存器, CPU 将这些寄存器当作端口来访问。
(2)CPU 在执行完当前指令后,可以检测到发送过来的中断信息,引发中断过程,处理外设的输入。
3.2 外中断信息
(1)在 PC 系统中,外中断源一共有两类:可屏蔽中断;不可屏蔽中断。
- 可屏蔽中断是 CPU 可以不响应的外中断
- 标志寄存器的 IF 位决定 CPU 是否响应可屏蔽中断
- 如果 IF=1 ,则 CPU 在执行完当前指令后响应中断,引发中断过程
- 如果 IF=0 ,则不响应可屏蔽中断。
- 内中断的中断类型码是在 CPU 内部产生的
- 可屏蔽外中断信息来自于 CPU 外部,中断类型码是通过数据总线送入 CPU 的
sti, 用于设置 IF=1
(1)标志寄存器入栈, IF=0, TF=0
(2)CS, IP 入栈
3.3 PC 机键盘的处理过程
- 按下一个键时,该芯片产生一个扫描码(通码通码,对应于按下键的位置),通码被送入主板上的相关接口芯片内端口地址为 60H 的寄存器。
- 松开按下的键时,产生扫描码(断码断码,对应于松开键的位置),断码被送入 60H 端口中。
- 扫描码长度为一个字节,通码的第 7 位为 0,断码的第 7 位为 1 ,即:断码 = 通码+ 80H
BIOS 提供 int 9 中断例程,处理基本键盘输入的过程
- 键盘产生扫描码
- CPU 读出 60H 端口中的扫描码
- 根据扫描码写键盘缓冲区
- 若字符键的扫描码,则将该扫描码及其对应的字 ASCII 码送入内存中的 BIOS 键盘缓冲区;
- 若是控制键(如 Ctrl )和切换键(如 CapsLock )的扫描码,则将其转变为状态字节写入内存中存储状态字节的单元。
- 引发 9 号中断;
- CPU 执行 int 9 中断例程处理键盘输入。
- BIOS 键盘缓冲区是系统启动后, BIOS 用于存放 int 9 中断例程所接收的键盘输入的内存区。
- 该内存区可以存储 15 个键盘输入,因为 int 9 中断 例程会生成扫描码对应的字符码, 所以在 BIOS 键盘缓冲区中,一个键盘输入用一个字单元存放,高位字节存放扫描码,低位字节存放字符码。
0040:17 单元存储键盘状态字节,该字节记录了控制 键和切换键的状态。键盘状态字节各位记录的信息 如下:
六、汇编语言总结
mov 、 push 、 pop 、 pushf 、 popf 、 xchg
add 、 sub 、 adc 、 sbb 、 inc 、 dec 、 cmp、 imul 、 idiv 、 aaa
and 、 or 、 not 、 xor 、 test 、 shl 、 shr 、 sal、 sar 、 rol 、 ror 、 rcl 、 rcr
除了 not 指令外,它们的执行结果都影响标志寄存器的相关标志位。
可以修改 IP ,或同时修改 CS 和 IP 的指令统称为转移指令。
( 2 )条件转移指令,如: jcxz 、 je 、 jb 、 ja 、 jnb 、 jna ;
( 4 )过程,比如: call 、 ret 、 retf ;
cld 、 std 、 cli 、 sti 、 nop 、 clc 、 cmc 、 stc、 hlt 、 wait 、 esc 、 lock
movsb 、 movsw 、 cmps 、 scas 、 lods 、 stos
若要使用这些指令方便地进行批量数据的处理,则需要和 rep 、 repe 、 repne 等前缀指令配合使用。
七、C语言
1. 宏定义与操作符的区别:宏定义是C++的预处理命令之一,它是一个替换操作,不做计算和表达式求解,不占内存和编译时间。
八、C++
1. 类:类定义了事物的属性和它可以做到的(它的行为)。一个类的方法和属性被称为“成员”。一个类所包含的方法和数据描述一组对象的共同属性和行为。类是在对象之上的抽象,对象则是类的具体化,是类的实例。
2. 封装性:封装使数据和加工该数据的方法(函数)封装为一个整体,把对象的设计者和对象的使用者分开,使用者不必知晓行为实现的细节,可以增加安全性。
3. 继承性:继承性是子类共享父类之间数据和方法的机制。一个类直接继承其它类的全部描述,同时可修改和扩充。可以增强代码的复用性。
4. 多态性:对象根据所接收的消息而做出动作。同一消息为不同的对象接受时可产生完全不同的行动,这种现象称为多态性。使具有不同内部结构的对象共享相同的外部接口。可以增加扩展性。
5. 虚函数与纯虚函数的特点:虚函数必须是基类的非静态成员函数,其访问权限可以是protected或public;纯虚函数是虚函数的一个子集,含有纯虚函数的类就是抽象类,它不能生成对象。
6. 如何使用纯虚函数:纯虚函数用来定义没有意义的实现,用于抽象类中需要交给派生类具体实现的方法。
7. 引用与值传递的区别:值传递传递的是一个值的副本,函数对形参的操作不会影响实参的值;引用传递传递的是引用对象的内存地址,函数对形参的操作会影响实参的值,实参的值会随着形参的值得改变而改变。
8. 指针与引用的区别:(1)引用无需解引用,指针需要解引用;(2)引用在定义时被初始化一次,之后不可变,指针可变;(3)引用不能为空,指针可以为空;(4)程序为指针变量分配内存区域,而引用不需要分配内存区域,所以指针自增操作是指针变量的自增,引用自增操作是变量值的自增。
9. 面向对象与面向过程的区别:面向过程是一种以过程为中心的编程思想,以算法进行驱动;面向对象是一种以对象为中心的编程思想,以消息进行驱动。面向过程编程语言的组成:程序=算法+数据;面向对象编程语言的组成:程序=对象+消息。
10. 面向对象的特征是什么:面对对象的3个要素:封装,继承,多态。面向对象中所有对象都可以归属为一个类。
11. 类与结构体有什么区别:(1)结构体存储在栈中,类的实例化可以存储在栈中,也可以存储在堆中;(2)结构体的执行效率比类要高;(3)结构体没有析构函数,类有析构函数;(4)结构体不可以继承,类可以继承。
12. C++覆盖与隐藏概述:(1)覆盖指的是在子类和父类中,存在函数名、参数均相同的函数,并且父类的该函数为虚函数;(2)隐藏指的是在子类与父类中,存在函数名相同、参数不同的函数,此时无论父类函数是否为虚函数,父类函数都会被被隐藏,或者存在函数名、参数均相同的函数,此时只有当父类函数不为虚函数时,父类函数才会被隐藏。
13. 内联函数:用来建议编译器对一些特殊函数进行内联扩展(有时称作在线扩展);也就是说建议编译器将指定的函数体插入并取代每一处调用该函数的地方(上下文),从而节省了每次调用函数带来的额外时间开支。在内联函数内不允许有循环语句和switch语句。
14. 什么是静态函数,如何使用静态函数:静态函数是用static修饰符修饰的函数,静态函数没有this指针,只能访问静态变量。类中如果函数调用的结果不会访问或者修改任何对象数据成员,这样的成员声明为静态成员函数比较好。
15. 函数重载及作用域:函数重载是指在相同作用域下,具有相同名称而不同参数列表的多个函数。
16. 什么是函数模板:函数模板技术是指使用了模板技术定义了参数化类型的非成员函数,这使得程序能够使用不同的参数类型调用相同的函数。
17. 什么是类模板:类模板是使用模板技术的类,描述了能够管理其他数据类型的通用数据类型。类模板技术通常用于建立包含其他类型的容器类(队列、链表、堆栈等)。
18. 什么是泛型编程:泛型编程就是以独立于特定类实现的方式编写代码,针对不同的类型提供通用的实现。
19. 什么是泛型编程:泛型编程就是以独立于特定类实现的方式编写代码,针对不同的类型提供通用的实现。
20. C++如何实现泛型编程:C++中泛型编程的实现是使用C++中的模板技术来实现的,主要是设计函数模板和类模板。
九、Java
Java 是由 C++发展而来的,保留了 C++的大部分内容,其编程方式类似于 C++。但 Java 的句法更清晰、规模更小、更易学。Sun 公司曾对多种程序设计语言进行分析研究,取其精华去其糟粕,最终推出了 Java。Java从根本上解决了C++的固有缺陷,形成了新一代面向对象的程序设计语言。
Java是一种解释性(或者说半解释半编译)语言,意味着其在执行时会被“翻译”为二进制形式,也就是java跑得时候必须有人(jvm)去解释它(现在的Java语言,其执行方式已经不仅仅是解释执行方式了,即时编译器(JITC、just-in-time compiler)技术和原型编译技术的出现大大提高了JAVA的运行效率)。而C++则是编译语言,意味着程序只能在特定操作系统上编译并在特定系统上运行,也就是说C++一步到位成机器语言的。
Java是一种内存安全型语言,意味着大家可以为给定数组分配任意参数,即使超出范围也只会返回错误提示。C++更为灵活,但代价是一旦分配的参数超出资源范围,则会引起错误甚至严重崩溃。
Java不支持多重继承。多重继承,它允许多父类派生一个子类。也就是说,一个类允许继承多个父类。尽管多重继承功能很强,但使用复杂,而且会引起许多麻烦,编译程序实现它也很不容易。所以 Java 不支持多重继承,但允许一个类实现多个接口。可见,Java 既保留了 C++多重继承的功能,又避免了 C++的许多缺陷。
Java 是完全面向对象的语言,所有方法和数据都必须是类的一部分。除了基本数据类型之外,其余类型的数据都作为对象型数据。例如,对象型数据包括字符串和数组。类将数据和方法结合起来,把它们封装在其中,这样每个对象都可实现具有自己特点的行为。Java 还取消了 C/C++中的结构和联合,使编译程序更加简洁。
Java 自动进行无用内存回收操作,不再需要程序员进行手动删除。Java 程序中所有的对象都是用 new 操作符建立在堆栈上的,这个操作符类似于 C++的“new”操作符。当 Java 中一个对象不再被用到时,无须使用内存回收器,只需要给它添加删除标签,无用内存的回收器便利用空闲时间在后台运行。而 C++中必须由程序释放内存资源,这就增加了程序员的负担。
Java 不支持操作符重载,操作符重载被认为是 C++的突出特征。操作符重载,就是把操作符(比如'+,-,*,/'这些运算符)赋于新的意义, 来完成更为细致具体的运算等功能。要实现操作符重载,就要使用操作符重载函数,而运用函数就肯定会存在各种限制条件以及特殊情况。特殊情况就需特殊处理,因此操作符重载还是比较繁琐的。Java语言是走“简洁风”的,因此为了保持Java语言的简洁性,便毅然抛弃了操作符重载这一功能,但是为了避免舍本逐末的情况,Java语言还是可以通过类来实现操作符重载所具有的功能的。
C/C++在编译过程中都有一个预编译阶段,即预处理器。预处理器为开发人员提供了方便,但增加了编译的复杂性。Java 允许预处理,但不支持预处理器功能,因为 Java 没有预处理器,所以为了实现预处理,它提供了引入语句(import),但它与 C++预处理器的功能类似。
Java 不支持缺省参数函数,而 C++支持 。在 C 语言中,代码组织在函数中,函数可以访问程序的全局变量。后来C++增加了类,提供了类算法,该算法是与类相连的函数,C++类方法与 Java 类方法十分相似。由于 C++仍然支持 C语言,所以 C++程序中仍然可以使用 C 的函数,结果导致函数和方法混合使用,使得 C++程序混乱,而Java 没有函数(准确说叫方法)。作为一个比 C++更纯的面向对象的语言,Java 强迫开发人员把所有例行程序包括在类中。事实上,用方法实现例行程序可激励开发人员更好地组织编码。
C 和 C++不支持字符串变量,在 C 和 C++程序中使用 NULL 终止符代表字符串的结束。在 Java 中字符串是用类对象(String 和 StringBuffer)来实现的,在整个系统中建立字符串和访问字符串元素的方法是一致的。Java 字符串类是作为 Java 语言的一部分定义的,而不是作为外加的延伸部分。此外,Java 还可以对字符串用“+”进行连接操作。
“可怕”的 goto 语句是 C 和 C++的“遗物”,它是该语言技术上的合法部分。goto语句也称为无条件转移语句,通常与条件语句配合使用,用来实现条件转移, 构成循环,跳出循环体等功能。但是,在结构化程序设计中一般不主张使用goto语句, 以免造成程序流程的混乱,使程序的可读性变差,增加程序调试的难度。 Java 不提供 goto 语句,虽然Java指定 goto 作为关键字,但不支持它的使用,这使程序更简洁易读。
在 C 和 C++中,有时会出现数据类型的隐含转换,这就涉及了自动强制类型转换问题。例如,在 C++中可将一个浮点值赋予整型变量,并去掉其尾数。Java 不支持 C++中的自动强制类型转换,如果需要,必须由程序显式进行强制类型转换。
java侧重于大型企业级应用开发,C++侧重于底层应用开发。Java是Android开发领域的王者,因此移动开发者无疑应该选择它作为项目基础。另外,Java也常见于Web及桌面应用乃至服务器端应用。
C++更接近机器语言,因此其软件运行速度更快且能够直接与计算机内存、磁盘、CPU或者其它设备进行协作。另外,C++也能为游戏提供良好的运行性能。