C/C++八股面试题(六)

目录:

1.请你说说动态链接与静态链接两者有什么区别?

2.请简单说说静态成员函数与普通成员函数的区别?

3.简述C++从代码到可执行二进制文件的过程?

4.全局变量和局部变量的区别?

5.C语言的基本类型有哪些(32位系统),占用字节空间?

6.头文件#ifndef/#define/#endif的作用?

内容:

1.请你说说动态链接与静态链接两者有什么区别?

动态链接的基本思想

  • 是把程序按照模块拆分成各个相对独立部分,在程序运行时才将它们链接在一起形成一个完整的程序。

动态链接

  • 从链接时机看:动态链接是在程序运行时完成的,即程序在运行时加载外部的共享库(如 .dll.so 文件)。
  • 从文件大小看:生成的可执行文件较小,因为它只包含调用库的引用,而不包含库的实际代码。
  • 从性能看:动态链接可能会略微影响程序启动速度,因为需要在运行时加载和解析库文件。
  • 从依赖上看:程序在运行时依赖外部的动态库,如果系统中缺少这些库或版本不匹配,程序可能无法正常启动或运行。动态链接的好处是库的更新不需要重新编译应用程序,只要保持接口一致即可。

静态链接的基本思想

  • 我们不可能将所有代码放在一个源文件中,所以会出现多个源文件,而且多个源文件之间不是独立的,而会存在多种依赖关系,如一个源文件可能要调用另一个源文件中定义的函数,但是每个源文件都是独立编译的,即每个.c文件会形成一个.o文件,所以就会有依赖关系,则需要将这些源文件产生的目标文件进行链接,从而形成一个可以执行的程序。这个链接的过程就是静态链接。

静态链接

  • 从链接时机看:静态链接在编译阶段完成,生成的可执行文件中包含了所有依赖库的代码和符号表。
  • 从文件大小看:生成的可执行文件相对较大,因为它包括了所有依赖的库文件。
  • 从性能看:由于库的代码已经被直接包含在可执行文件中,因此程序的加载速度较快,运行时不需要查找和加载外部库。
  • 从依赖上看:程序在运行时不依赖外部的库文件,减少了运行时出现版本不兼容的问题。但如果库有更新,程序需要重新编译。

总结对比

链接时机

编译时

运行时

可执行文件大小

较大

较小

启动速度

较快

较慢(需要加载共享库)

依赖管理

运行时不依赖外部库

运行时依赖外部库

库更新

库更新需要重新编译程序

库更新无需重新编译程序

共享性

每个程序都有独立的库副本

多个程序可以共享相同的库

2.请简单说说静态成员函数与普通成员函数的区别?

访问对象

  • 普通成员函数:普通成员函数是与类的实例(对象)关联的函数。它必须通过对象来调用,并且在函数内部可以访问该对象的所有成员变量和成员函数。在成员函数内部,可以使用this指针来访问对象的成员变量。obj.func()这种调用可以理解为:myClass::func(&obj)
  • 静态成员函数:静态成员函数是与类本身关联的,而不是与类的某个具体对象关联。它可以直接通过类名来调用,不需要先创建对象。

访问成员变量

  • 普通成员函数:可以访问类的所有成员,包括静态成员和非静态成员包括私有成员。
  • 静态成员函数:只能访问静态成员变量和静态成员函数。它不能访问非静态成员变量和非静态成员函数,因为静态成员函数在类的实例化对象未创建时就已经存在,它无法指向某个具体对象。

this 指针

  • 普通成员函数:每个普通成员函数都有一个隐式的this指针,指向当前调用该成员函数的对象。通过this指针,可以访问对象的成员变量和成员函数。
  • 静态成员函数:静态成员函数没有this指针,因为它不是与某个对象关联的。因此,静态成员函数无法通过this指针来访问成员变量和成员函数。

调用方式

  • 普通成员函数:必须通过类的对象来调用,或者通过指针/引用访问。
class MyClass {
public:
    void normalFunc() { // 普通成员函数
        std::cout << "This is a normal function" << std::endl;
    }
};

MyClass obj;
obj.normalFunc();  // 通过对象调用

  • 静态成员函数:可以通过类名直接调用,也可以通过对象调用,但推荐通过类名调用。
class MyClass {
public:
    static void staticFunc() { // 静态成员函数
        std::cout << "This is a static function" << std::endl;
    }
};

MyClass::staticFunc();  // 通过类名调用
MyClass obj;
obj.staticFunc();  // 也可以通过对象调用

总结对比

调用方式

必须通过对象来调用

可以通过类名或对象来调用

访问成员变量

可以访问所有非静态和静态成员

只能访问静态成员,不能访问非静态成员

this

指针

this

指针,指向当前对象

没有

this

指针

适用场景

当需要操作对象的状态或成员时使用

当需要与类本身相关,但不需要访问对象时使用

3.简述C++从代码到可执行二进制文件的过程

预处理

  • 预处理是编译过程的第一步,它的主要任务是处理所有的预处理指令(如 #include#define 等),并生成一个纯净的 C++ 源代码文件。生成一个预处理后的 .i 文件,其中包含了宏替换、头文件内容和注释已去除的代码。

编译

  • 编译阶段的主要任务是将预处理后的源代码转换成汇编语言代码。编译器会对源代码进行语法分析、词法分析、语义分析等,生成对应的汇编语言代码。生成一个汇编语言文件(.s 文件),其中包含了计算机能理解的低级汇编指令。

汇编

  • 汇编阶段将生成的汇编语言代码转化为机器码(对象代码),并生成目标文件(.o.obj 文件)。汇编器将汇编代码转换成机器语言代码,但尚未处理代码中可能存在的外部依赖(如函数调用和全局变量)。生成一个目标文件(.o.obj),它包含机器代码和符号信息,但还未能完全独立执行。

链接

  • 链接是将一个或多个目标文件与所需的库文件(如标准库、第三方库等)合并成一个完整的可执行文件的过程。链接分为两个阶段:静态链接动态链接。生成一个完整的可执行二进制文件(通常是 .exe 文件,在 Unix 系统中是没有扩展名或 .out),此时的程序可以独立运行。

可执行文件

  • 最终,经过链接生成的可执行文件是程序可以运行的形式。它包含了所有的代码、数据和必要的符号信息,操作系统可以将其加载到内存中执行。

总结:

预处理

处理宏定义、头文件包含、条件编译等

预处理后的源代码文件(.i

编译

将源代码转化为汇编语言

汇编语言文件(.s

汇编

将汇编语言转化为机器码

目标文件(.o.obj

链接

合并多个目标文件和库文件,解析符号

可执行文件(如 .exe或无扩展名)

4.全局变量和局部变量的区别?

作用域

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

嵌入式/C++八股 文章被收录于专栏

本人双飞本,校招上岸广和通。此专栏覆盖嵌入式常见面试题,有C/C++相关的知识,数据结构和算法也有嵌入式相关的知识,如操作系统、网络协议、硬件知识。本人也是校招过来的,大家底子甚至项目,可能都不错,但是在面试准备中常见八股可能准备不全。此专栏很适合新手学习基础也适合大佬备战复习,比较全面。最终希望各位友友们早日拿到心仪offer。也希望大家点点赞,收藏,送送小花。这是对我的肯定和鼓励。 持续更新

全部评论
欢迎大家订阅此专栏,订阅点赞收藏送花后,截图si聊我,免费赠送嵌入式学习资料大礼包(含简历模版、c/c++、嵌入式等资料)
5 回复 分享
发布于 2024-12-14 15:53 陕西
问个问题,那静态成员可以访问非静态成员吗,求解答
2 回复 分享
发布于 2024-12-14 18:51 陕西
加更加更
1 回复 分享
发布于 2024-12-15 22:02 陕西
1 回复 分享
发布于 2024-12-22 10:56 陕西
求加更 要复习
点赞 回复 分享
发布于 01-21 17:32 陕西

相关推荐

01-21 12:26
暨南大学 golang
点赞 评论 收藏
分享
评论
20
25
分享

创作者周榜

更多
牛客网
牛客企业服务