兴业数金8月5日笔试总结

笔试基本信息:
时间:120分钟
分数:单选题40题(共40分),多选题20题(共40分),编程题1题(共20分)
知识点:主要包括C++基本语法(sizeof,关键字,do...while,extern,volatile,i++与++i),基本数据类型以及数组内存,MySQL知识(很多题目)等,编程题为动态规划平方和(力扣279)
防作弊措施:共享屏幕,锁手机微信

关键知识总结:

sizeof问题与内存对齐

  • 指针类型的sizeof

指针用来存放地址,那么它就等于计算机内部地址总线的宽度。所以在32位计算机中,指针的返回值是4(以字节为单位),在64位系统中指针变量的返回值为8

  • 数组的sizeof

数组的sizeof值等于数组所占用的内存字节数。

char a1[] = "abc"; 

int a2[3]; 

sizeof( a1 ); // 结果为4,字符串末尾还存在一个NULL终止符 

sizeof( a2 ); // 结果为3*4=12(依赖于int)
  • 结构体的sizeof
struct S1{char c;int i;};

问sizeof(S1)等于多少聪明的你开始思考了,char占1个字节,int占4个字节,那么加起来就应该是5。是这样吗?你在你机器上试过了吗?也许你是对的,但很可能你是错的!VC6中按默认设置得到的结果为8。

这就引出了内存对齐问题:

why?这样做有助于加快计算机的取数速度,否则就得多花指令周期了。为此,编译器对数据进行处理,让宽度为2的基本数据类型(short等)都位于能被2整除的地址上,让宽度为4的基本数据类型都位于能被4整除的地址上。这样两个数中间就可能需要加入填充字节,所以整个结构体的sizeof值就正常了。

那么交换char与int的位置之后,内存为多少位呢?

struct S1{int i ; char c;};

发现还是8位,成员c后面还是有三个填充字节。因为字节对齐需要满足三个准则:

  1. 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;
  2. 结构体每个成员相对结构体首地址的偏移量都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节、
  3. 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节
  • 联合体的sizeof

结构体在内存组织上是顺序式的,联合体则是重叠式,各成员共享一段内存,所以整个联合体的sizeof也就是每个成员sizeof的最大值。结构体的成员也可以是复合类型,这里,复合类型成员是被作为整体考虑的。

  • 类的sizeof

1.空类的sizeof是1

2.若类中包含成员,则类对象的大小只包括其中非静态成员经过对齐所占的空间,对齐方式和结构体相同

3.若类中包含虚函数,sizeof类都等于sizeof(数据成员)+sizeof(虚表,为4)

4.对于子类,它的sizeof是它父类成员(无论成员是public或private),再加上它自己的成员,对齐后的sizeof

5.对于子类和父类中都有虚函数的情况,子类的sizeof是它父类成员(无论成员是public或private),再加上它自己的成员,对齐后的sizeof,再加4(虚表指针)

6.对于虚继承的子类,其sizeof的值是其父类成员,加上它自己的成员,以及它自己一个指向父类的指针(大小为4),对齐后的sizeof。

7.对于既有虚继承又有虚函数的子类,其sizeof的值是其父类成员(计算虚表指针大小+4),加上它自己的成员(计算虚表指针大小+4),以及它自己一个指向父类的指针(大小为4),对齐后的sizeof。

extern关键字的作用

extern有两个作用:

  1. 当它与“C”一起连用时,表示编译器编译时按照C的规则去翻译相应的函数名而不是C++的(因为C++有函数重载)
  2. 当它不与“C”在一起修饰变量或函数时,它的作用就是声明函数或全局变量的作用范围的关键字,其声明的函数或变量可以在本模块或者其他模块中使用

i++与++i

#include<stdio.h>
int main()
{
    int i = 2;
    int j = 2;
    j += i++;//先赋值后加
    printf("i= %d, j= %d\n",i, j); //i= 3, j= 4
    i = 2;
    j = 2;
    j += ++i;//先加后赋值
    printf("i= %d, j= %d",i, j); //i= 3, j= 5

}
  1. 赋值顺序不同:++ i 是先加后赋值;i ++ 是先赋值后加;++i和i++都是分两步完成的。
  2. 效率不同:后置++执行速度比前置的慢
  3. i++不能作为左值,而++i可以
  4. 二者都不是原子操作

volatile关键字的作用

编译器在存取变量时,为提高存取速度,编译器优化有时会先把变量读取到一个寄存器中;以后再取变量值时就直接从寄存器中取值。但在很多情况下会读取到脏数据,严重影响程序的运行效果。

原理作用:

volatile意思是“易变的”,应该解释为“直接存取原始内存地址”比较合适

“易变”是因为外在因素引起的,像多线程和中断等

volatile关键词影响编译器编译的结果,用volatile声明的变量表示该变量随时可能发生变化,与该变量有关的运算,不要进行编译优化,而是直接从变量内存地址中读取数据,以免出错

一般用处:

1.中断服务程序中修改的供其他程序检测的变量,需要加volatile;

当变量在触发某中断程序中修改,而编译器判断主函数里面没有修改该变量,因此可能只执行一次从内存到某寄存器的读操作,而后每次只会从该寄存器中读取变量副本,使得中断程序的操作被短路。

2.多任务环境下各任务间共享的标志,应该加volatile;

在本次线程内, 当读取一个变量时,编译器优化时有时会先把变量读取到一个寄存器中;以后,再取变量值时,就直接从寄存器中取值;当内存变量或寄存器变量在因别的线程等而改变了值,该寄存器的值不会相应改变,从而造成应用程序读取的值和实际的变量值不一致 。

3 存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能由不同意义;

假设要对一个设备进行初始化,此设备的某一个寄存器为0xff800000。for(i=0;i< 10;i++) *output = i;前面循环半天都是废话,对最后的结果毫无影响,因为最终只是将output这个指针赋值为9,省略了对该硬件IO端口反复读的操作。

全部评论
大佬,记录的好多
点赞 回复 分享
发布于 2022-08-05 20:53
请问大佬面的是什么岗位?
点赞 回复 分享
发布于 2022-08-06 01:26
请问你是什么时间投的
点赞 回复 分享
发布于 2022-08-12 10:26
锁手机微信是啥意思
点赞 回复 分享
发布于 2022-08-18 22:37 福建

相关推荐

评论
5
30
分享
牛客网
牛客企业服务