面试八股
内存对齐
1、什么是内存对齐?
假设我们同时声明两个变量: char a; short b; 用&(取地址符号)观察变量a, b的地址的话,我们会发现(以16位CPU为例): 如果a的地址是0x0000,那么b的地址将会是0x0002或者是0x0004。 那么就出现这样一个问题:0x0001这个地址没有被使用,那它干什么去了? 答案就是它确实没被使用。 因为CPU每次都是从以2字节(16位CPU)或是4字节(32位CPU)的整数倍的内存地址中读进数据的。如果变量b的地址是0x0001的话,那么CPU就需要先从0x0000中读取一个short,取它的高8位放入b的低8位,然后再从0x0002中读取下一个short,取它的低8位放入b的高8位中,这样的话,为了获得b的值,CPU需要进行了两次读操作。 但是如果b的地址为0x0002, 那么CPU只需一次读操作就可以获得b的值了。所以编译器为了优化代码,往往会根据变量的大小,将其指定到合适的位置,即称为内存对齐(对变量b做内存对齐,a、b之间的内存被浪费,a并未多占内存)。
**2、结构体内存对齐规则(请记住三条内存规则(在没有#pragam pack宏的情况下) 结构体所占用的内存与其成员在结构体中的声明顺序有关,其成员的内存对齐规则如下: **
(1)每个成员分别按自己的对齐字节数和PPB(指定的对齐字节数,32位机默认为4)两个字节数最小的那个对齐,这样可以最小化长度。如在32bit的机器上,int的大小为4,因此int存储的位置都是4的整数倍的位置开始存储。
(2)复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,结构体数组的时候,可以最小化长度。
(3)结构体对齐后的长度必须是成员中最大的对齐参数(PPB)的整数倍,这样在处理数组时可以保证每一项都边界对齐。
(4)结构体作为数据成员的对齐规则:在一个struct中包含另一个struct,内部struct应该以它的最大数据成员大小的整数倍开始存储。如 struct A 中包含 struct B, struct B 中包含数据成员 char, int, double,则 struct B 应该以sizeof(double)=8的整数倍为起始地址。
i++和++i哪个效率更高?
因为前缀式(++i)可以返回对象的引用,而后缀式必须返回对象的值,所有导致在大对象的时候产生了较大的复制开销,引起效率降低。
因此
内建数据类型的情况,效率没有区别。
自定义数据类型的情况,++i效率更高。
C和C++有何不同?
C是一个结构化语言,他4它的重点在于算法与数据结构。对于语言本身,C是C++的子集。C程序的设计首先要考虑的是如何通过一个过程,对输入进行运算处理,得到输出,对于C++,首先要考虑的是如何构造一个对象模型,让这个模型能够配合对应的问题,这样就可以通过获取对象的状态 信息得到输出或实现过程控制。
C实现了C++中过程化控制及其他相关功能。而在C++中的C,相对于原来的C有所加强,引入了重载、内联函数、异常处理等。C++是拓展面向对象设计的内容,如类、继承。虚函数模板和包容器类等。
在C++中,不仅需要考虑数据封装,还需要考虑对象粒度的选择、对象接口的设计和继承、组合与继承的使用等问题。
C++中main函数执行完后还执行其它语句吗?
可以用atexit()
函数来注册程序正常终止时要被调用的函数,并且在main函数结束时调用这些函数的顺序与注册它们时的顺序相反。
宏参数的连接
在这个程序中,使用#把宏参数变为一个字符串,用##把两个宏参数贴合在一起。
用宏定义得到一个字的低位和高位字节
一个字由两个字节组成。因此WORD_LO(xxx)
取参数xxx的低8位。WORD_HI(xxx)
取参数xxx的高8位.
用宏定义得到一个数组所含元素的个数
const与#define的特点及区别
#define
只是用来做文本替换的。在程序进行编译时完成替换,#define
是一个Compile-Time
概念,它的生命周期止于编译期,它存在于程序的代码段,在实际程序中它只是一个常数,一个命令中的参数,并没有实际的存在。
const
常量存在于程序的数据段,并在堆栈分配了空间。const
常量是一个Run-Time
概念,它在程序中确确实实的存在着并可以被调用、传递。const
常量有数据类型,而宏常量没有数据类型。编译器可以对const
常量进行安全检查。
C++中const有什么作用
-
用于定义常量。
-
修饰函数形参。用”引用传递“不需要产生临时对象,节省了临时对象的构造、复制、析构过程消耗的时间,但光用引用有可能改变形参值,所有加const。当输入参数为用户自定义类型和抽象数据类型时,应该将“值传递“改为”const&传递“可以提高效率。
-
const修饰函数的返回值。如给“指针传递”的函数返回值加const,则返回值不能被直接修改,且该返回值只能被赋值给加const修饰的同类型指针。
-
const修饰类的成员函数(函数定义体)。任何不会修改数据成员的函数都应应用const修饰,这样,当不小心修改了数据成员或调用了非const成员函数时,编译器都会报错。
static有什么作用
- 在函数体,一个被声明为静态的变量在这一函数被调用的过程中维持其值不变。
- 在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所有函数访问,但不能被模块外的其它函数访问。它是一个本地的全局变量。
- 在模块内一个被声明为静态的函数只可被这一模块内的其它函数调用。那就是这个函数被限制在声明它的模块的本地范围内使用。
关键字volatile有什么含意?并举出三个不同的例⼦?
关键字static的作⽤是什么?
在C语⾔中,为什么 static变量只初始化⼀次?
- 本文作者: hzr
- 本文链接: https://HZR0709.github.io/2024/06/12/An eight-part essay/
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!