目录
C语言和C++的区别
C++和Java的区别
代码到可执行程序的过程
静态链接和动态链接的区别
动态库和静态库
C语言和C++的区别
- C语言是C++的子集,C++可以很好兼容C语言。但是C++又有很多新特性,如右值引用、智能指针、类型转换等。
- C++是面向对象的编程语言;C语言是面向过程的编程语言。
- C++提供了类、对象、继承、多态等特性,使得程序设计更加模块化和易于维护。
- 标准模板库(STL):C++提供了一套强大的标准模板库,包括容器、迭代器、算法等组件,可以大大提高编程效率。而C语言没有类似的库。
- C++中new和delete是对内存分配的运算符,取代了C中的malloc和free。
- 标准C++中的字符串类取代了标准C函数库头文件中的字符数组处理函数(C中没有字符串类型)。
- C++中用来做控制态输入输出的iostream类库替代了标准C中的stdio函数库。
- C++中的try/catch/throw异常处理机制取代了标准C中的setjmp()和longjmp()函数。
- 在C++中,允许有相同的函数名,不过它们的参数类型不能完全相同,这样这些函数就可以相互区别开来。而这在C语言中是不允许的。也就是C++可以重载,C语言不允许。
- C++相对与C增加了一些关键字,如:bool、using、dynamic_cast、namespace等等
C++和Java的区别
编译和解释:
- C++是一种编译型语言,这意味着代码需要先被编译成机器语言,然后才能运行。
- Java是一种解释型语言,这意味着代码在运行时由Java虚拟机(JVM)逐行解释执行。
当Java程序开始运行时,JVM会将源代码文件转换为一种中间形式的代码(字节码),然后再由JVM解释执行这些字节码。
编译型语言(如C++)的代码在运行前就已经被完全编译成机器语言,因此其执行速度通常更快。
内存管理:
- C++允许程序员直接管理内存,这使得程序员可以更精确地控制程序的内存使用。然而,这也意味着程序员需要自己处理内存泄漏等问题。
- Java自动管理内存,程序员不需要担心这些问题。
内存管理是由JVM(Java虚拟机)自动完成的。当创建一个对象时,JVM会在堆内存中为该对象分配一块空间。当程序不再需要这个对象时,JVM会自动回收这块空间,将其归还给操作系统。
平台独立性:
- Java的一个重要特点是“一次编写,到处运行”,这是因为Java代码在运行时被编译成字节码,然后由JVM在目标平台上解释执行。这意味着只要目标平台上安装了JVM,Java程序就可以在该平台上运行。
- C++代码通常需要针对特定的平台进行编译,因此其可移植性较差。
面向对象:
- C++和Java都是面向对象的编程语言,但它们的面向对象实现方式略有不同。C++支持多重继承,而Java不支持多重继承,只支持单继承和接口继承。
- C++中的对象可以直接访问其成员变量和方法,而Java中的对象只能通过getter和setter方法访问成员变量。
语法:
- C++的语法相对复杂,包括指针、模板等高级特性。
- Java的语法相对简单,易于学习和使用。
代码到可执行程序的过程
(1)预处理
- 删除所有的#define,展开所有的宏定义。
- 处理所有的条件预编译指令,如“#if”、“#endif”、“#ifdef”、“#elif”和“#else”。
- 处理“#include”,将文件内容替换到它的位置,这个过程是递归进行的,文件中包含其他文件。
- 删除所有的注释。
- 保留所有的#pragma 编译器指令,编译器需要用到他们,如:#pragma once 是为了防止有文件被重 复引用。
- 最终形成xxx.i文件。
(2)编译
- 将源代码的字符序列分割成一系列的记号
- 对记号进行语法分析
- 生成汇编代码
- 最终形成xxx.s文件。
(3)汇编
将汇编代码转变成机器可以执行的指令(将汇编代码变成二进制文件)
最终形成xxx.o文件。
(4)链接
- 将不同的源文件产生的目标文件进行链接, 从而形成一个可执行的程序
- 链接分为静态链接和动态链接
- 把我自己写的文件和库中的文件链接起来
- 将生成的各个xxx.o文件进行链接,最终形成可执行程序。
将不同的源文件产生的目标文件进行链接,从而形成一个可以执行的程序。
(5)装载
操作系统或运行时环境负责将可执行程序装入内存,并在计算机上运行。在这一步骤中,操作系统为程序分配内存空间,并将程序的指令和数据加载到内存中,然后启动程序的执行。
(6)执行
一旦可执行程序被加载到内存中,CPU开始执行其中的指令。程序执行的过程包括处理输入、执行算法、生成输出等操作,直到程序终止。
静态链接和动态链接的区别
- 静态链接, 是在链接的时候就把要调用的函数的实现拷贝到可执行文件中, 这时就算把静态库删除了, 也不会影响可执行程序的执行. 优点在于程序在发布时不需要依赖库,可以独立执行. 缺点在于程序的体积会相对较大,而且如果静态库更新之后,所有可执行文件需要重新链接
- 动态链接, 是在链接的时候把要调用的函数的地址填写到可执行程序中, 建立关联, 将来要用的话直接跳转过去. 执行可执行文件的时候, 就拿着这个函数的地址到动态库中去查找并调用. 如果把动态库删除了, 可执行程序就不能成功运行. 优点在于多个程序可以共享同一个动态库,节省资源, 缺点在于由于运行时加载,可能影响程序的前期执行性能
- Windows下(.dll为动态库, .lib静态库)
- Linux下(.so为动态库, .a为静态库)
- 动态链接必须使用.so动态库文件. 静态链接必须使用.a静态库文件
- gcc/g++/vs, 默认是动态链接的
- gcc test.c -o test -static 加上-static选项就是静态链接的方式形成可执行程序
动态库和静态库
静态库
静态库是程序在编译链接的时候把库的代码复制到可执行文件当中的,生成的可执行程序在运行的时候将不再需要静态库,因此使用静态库生成的可执行程序的大小一般比较大。
- 优点:
使用静态库生成可执行程序后,该可执行程序就可以独自运行,不再需要库了。
- 缺点:
使用静态库生成可执行程序会占用大量空间,特别是当有多个静态程序同时加载而这些静态程序使用的都是相同的库,这时在内存当中就会存在大量的重复代码。
使用ar命令将所有目标文件打包为静态库
- -r(replace):若静态库文件当中的目标文件有更新,则用新的目标文件替换旧的目标文件。
- -c(create):建立静态库文件。
$ ar -rc libcal.a add.o sub.o
动态库
动态库是程序在运行的时候才去链接相应的动态库代码的,多个程序共享使用库的代码。一个与动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个表,而不是外部函数所在目标文件的整个机器码。
动态库在多个程序间共享,节省了磁盘空间,操作系统采用虚拟内存机制允许物理内存中的一份动态库被要用到该库的所有进程共用,节省了内存和磁盘空间。
- 优点:
节省磁盘空间,且多个用到相同动态库的程序同时运行时,库文件会通过进程地址空间进行共享,内存当中不会存在重复代码。
- 缺点:
必须依赖动态库,否则无法运行。
第一步:让所有源文件生成对应的目标文件
此时用源文件生成目标文件时需要携带-fPIC选项:
- -fPIC:产生位置无关码。
gcc -fPIC -c add.c
gcc -fPIC -c sub.c
第二步:使用-shared选项将所有目标文件打包为动态库
$ gcc -shared -o libcal.so add.o sub.o
Windows下(.dll为动态库, .lib静态库)
Linux下(.so为动态库, .a为静态库)文章来源:https://uudwc.com/A/6znGx
二者对比:文章来源地址https://uudwc.com/A/6znGx
- 类型检查:在静态库中,类型信息在编译时被嵌入到可执行文件中。这意味着链接器可以在运行时进行类型检查,因为所有符号都已知其类型。动态库中,类型信息通常在运行时解析,这可能导致运行时错误。
- 内存占用:由于静态库包含完整的代码和数据,它们通常比动态库占用更多的磁盘空间和内存。这可能会导致加载时间较长,以及更大的应用程序大小。
- 更新和维护:与静态库相比,动态库更容易更新和维护。当需要更改库的实现时,只需替换动态库文件即可,而无需重新编译使用该库的程序。多个程序可以共享同一个动态库,从而减少了磁盘空间的使用。
- 兼容性:静态库生成的可执行文件具有较好的兼容性,因为它们不依赖于外部库。然而,动态库可能需要针对特定的操作系统和编译器进行编译,这可能导致生成的可执行文件在其他平台上无法运行。
- 性能:由于静态库包含了完整的代码和数据,它们在运行时不需要额外的解析过程。因此,在某些情况下,静态库可能具有更好的性能。