打工人的面试题集锦
时间:2021-09-03 10:08:23
手机看文章
扫描二维码
随时随地手机看文章
[导读]前言: 经常回顾C/C面试题和笔试题,有助于我们对C/C基础有一个新的认识和记忆。在实际工作中,大部分人会被业务缠身,基础慢慢的遗忘了,对很多基础知识欲言又止!回顾笔试面试题目,会让我们对基础知识掌握更加牢固,同时笔试题也有助于我们开阔思路,提高编程能力,还有就是开源代码阅读,只...
前言: 经常回顾C/C 面试题和笔试题,有助于我们对C/C 基础有一个新的认识和记忆。在实际工作中,大部分人会被业务缠身,基础慢慢的遗忘了,对很多基础知识欲言又止!回顾笔试面试题目,会让我们对基础知识掌握更加牢固,同时笔试题也有助于我们开阔思路,提高编程能力,还有就是开源代码阅读,只有不断的回顾和学习,才能不断的进步。加油吧!打工人!~面试题 1:内存对齐的原则以及作用?
(1)结构体内的成员按自身长度自对齐(32位机器上,如char=1,short=2,int=4,double=8),所谓自对齐是指该成员的起始地址必须是它自身长度的整数倍。如int只能以0,4,8这类地址开始。
(2)结构体的总大小为结构体的有效对齐值的整数倍(默认以结构体中最长的成员长度为有效值的整数倍,当用#pragrma pack(n)指定时,以n和结构体中最长的成员的长度中较小者为其值)。即sizeof的值,必须是其内部最大成员的整数倍,不足的要补齐。
例如:
class A
{
char c;
int a;
char d;
};
cout << sizeof(A) << endl;
class B
{
char c;
char d;
int a;
};
cout << sizeof(B) << endl;
sizeof(A)=12,sizeof(B)=8;
因为左边是1 (3) 4 1 (3)=12,而右边是1 1 (2) 4=8。括号中为补齐的字节。
内存对齐的作用:
1、平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
2、性能原因:经过内存对齐后,CPU的内存访问速度大大提升。
面试题 2:变量的声明和定义有什么区别为变量分配地址和存储空间的称为定义,不分配地址的称为声明。一个变量可以在多个地方声明,但是只在一个地方定义。加入 extern 修饰的是变量的声明,说明此变量将在文件以外或在文件后面部分定义。说明:很多时候一个变量,只是声明不分配内存空间,直到具体使用时才初始化,分配内存空间, 如外部变量。面试题 3:explicit关键字的作用C 中, 一个参数的 构造函数(或者除了第一个参数外其余参数都有默认值的多参构造函数), 承担了两个角色。1 是个 构造器 ,2 是个默认且隐含的类型转换操作符。
所以, 有时候在我们写下如 AAA = XXX, 这样的代码, 且恰好XXX的类型正好是AAA单参数构造器的参数类型, 这时候 编译器就自动调用这个构造器, 创建一个AAA的对象。
这样看起来好象很酷, 很方便。但在某些情况下(见下面权威的例子), 却违背了我们(程序员)的本意。这时候就要在这个构造器前面加上explicit修饰, 指定这个构造器只能被明确的调用/使用, 不能作为类型转换操作符被隐含的使用。
class Test1
{
public:
Test1(int n)
{
num=n;
}//普通构造函数
private:
int num;
};
class Test2
{
public:
explicit Test2(int n)
{
num=n;
}//explicit(显式)构造函数
private:
int num;
};
int main()
{
Test1 t1=12;//隐式调用其构造函数,成功
Test2 t2=12;//编译错误,不能隐式调用其构造函数
Test2 t2(12);//显式调用成功
return 0;
}
Test1的 构造函数带一个int型的参数,代码23行会隐式转换成调用Test1的这个构造函数。而Test2的构造函数被声明为explicit(显式),这表示不能通过隐式转换来调用这个构造函数,因此代码24行会出现编译错误。
普通构造函数能够被 隐式调用。而explicit构造函数只能被显式调用。
面试题 4:写出 bool 、int、 float、指针变量与“零值”比较的 if 语句bool 型数据:
if( flag )
{
A;
}
else
{
B;
}
int 型数据:
if( 0 != flag )
{
A;
}
else {
B;
}
指针型数:
if( NULL == flag )
{
A;
}
else {
B;
}
float 型数据:
if ( ( flag >= NORM )
(1)结构体内的成员按自身长度自对齐(32位机器上,如char=1,short=2,int=4,double=8),所谓自对齐是指该成员的起始地址必须是它自身长度的整数倍。如int只能以0,4,8这类地址开始。
(2)结构体的总大小为结构体的有效对齐值的整数倍(默认以结构体中最长的成员长度为有效值的整数倍,当用#pragrma pack(n)指定时,以n和结构体中最长的成员的长度中较小者为其值)。即sizeof的值,必须是其内部最大成员的整数倍,不足的要补齐。
例如:
class A
{
char c;
int a;
char d;
};
cout << sizeof(A) << endl;
class B
{
char c;
char d;
int a;
};
cout << sizeof(B) << endl;
sizeof(A)=12,sizeof(B)=8;
因为左边是1 (3) 4 1 (3)=12,而右边是1 1 (2) 4=8。括号中为补齐的字节。
内存对齐的作用:
1、平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
2、性能原因:经过内存对齐后,CPU的内存访问速度大大提升。
面试题 2:变量的声明和定义有什么区别为变量分配地址和存储空间的称为定义,不分配地址的称为声明。一个变量可以在多个地方声明,但是只在一个地方定义。加入 extern 修饰的是变量的声明,说明此变量将在文件以外或在文件后面部分定义。说明:很多时候一个变量,只是声明不分配内存空间,直到具体使用时才初始化,分配内存空间, 如外部变量。面试题 3:explicit关键字的作用C 中, 一个参数的 构造函数(或者除了第一个参数外其余参数都有默认值的多参构造函数), 承担了两个角色。1 是个 构造器 ,2 是个默认且隐含的类型转换操作符。
所以, 有时候在我们写下如 AAA = XXX, 这样的代码, 且恰好XXX的类型正好是AAA单参数构造器的参数类型, 这时候 编译器就自动调用这个构造器, 创建一个AAA的对象。
这样看起来好象很酷, 很方便。但在某些情况下(见下面权威的例子), 却违背了我们(程序员)的本意。这时候就要在这个构造器前面加上explicit修饰, 指定这个构造器只能被明确的调用/使用, 不能作为类型转换操作符被隐含的使用。
class Test1
{
public:
Test1(int n)
{
num=n;
}//普通构造函数
private:
int num;
};
class Test2
{
public:
explicit Test2(int n)
{
num=n;
}//explicit(显式)构造函数
private:
int num;
};
int main()
{
Test1 t1=12;//隐式调用其构造函数,成功
Test2 t2=12;//编译错误,不能隐式调用其构造函数
Test2 t2(12);//显式调用成功
return 0;
}
Test1的 构造函数带一个int型的参数,代码23行会隐式转换成调用Test1的这个构造函数。而Test2的构造函数被声明为explicit(显式),这表示不能通过隐式转换来调用这个构造函数,因此代码24行会出现编译错误。
普通构造函数能够被 隐式调用。而explicit构造函数只能被显式调用。
面试题 4:写出 bool 、int、 float、指针变量与“零值”比较的 if 语句bool 型数据:
if( flag )
{
A;
}
else
{
B;
}
int 型数据:
if( 0 != flag )
{
A;
}
else {
B;
}
指针型数:
if( NULL == flag )
{
A;
}
else {
B;
}
float 型数据:
if ( ( flag >= NORM )