1.int *a[10] 类型为指针数组,int (*a)[10]类型为数组指针
2.定义指向int sum(int a,int b);的函数指针 int (*f)(int,int);f=sum;,该函数指针类型的大小为10的数组为 int (*f[10])(int ,int);
扩展: 指向该函数指针类型数组的指针为 int (*(*f[10]) )(int ,int);
3.输出为12,11,4,4
void fun(char str[10]){ printf("%d ", sizeof(str)); } int main(){ char str[] = "hello world"; printf("%d ", sizeof(str)); printf("%d ", strlen(str)); char*p = str; printf("%d ", sizeof(p)); fun(str); return 0; }
4.Parent虚表存储的是Parent::fun1,Parent::fun2,Child1虚表存储的是Child1::fun1,Parent::fun2,Child2虚表存储的是Child2::fun1,Child2::fun2
class Parent{ public: virtual void fun1(); virtual void fun2(); void fun3(); }; class Child1:public Parent{ public: void fun1(); void fun3(); }; class Child2 :public Child1{ public: void fun1(); void fun2(); void fun3(); };
5.析构函数必须为虚函数吗,为什么?
不是,析构函数声明为虚函数是在用基类指针指向该子类对象时,释放基类指针时可以释放掉子类的空间,防止内存泄漏。
6.哪几种情况下不能在类的构造函数中初始化,只能在初始化列表中进行初始化
const类型成员变量,引用类型成员变量,类成员为没有默认构造函数的类类型,如果类存在继承关系,派生类必须在其初始化列表中调用基类的构造函数
7.windows中lib文件和dll文件区别?生成DLL有两种模式,MT类型和MD类型的区别?使用时要注意的问题
lib与dll区别:
(1)lib是编译时用到的,dll是运行时用到的。如果要完成源代码的编译,只需要lib;如果要使动态链接的程序运行起来,只需要dll。
(2)如果有dll文件,那么lib一般是一些索引信息,记录了dll中函数的入口和位置,dll中是函数的具体内容;如果只有lib文件,那么这个lib文件是静态编译出来的
,索引和实现都在其中。使用静态编译的lib文件,在运行程序时不需要再挂动态库,缺点是导致应用程序比较大,而且失去了动态库的灵活性,发布新版本时
要发布新的应用程序才行。
(3)动态链接的情况下,有两个文件:一个是LIB文件,一个是DLL文件。LIB包含被DLL导出的函数名称和位置,DLL包含实际的函数和数据,应用程序使用LIB文
件链接到DLL文件。在应用程序的可执行文件中,存放的不是被调用的函数代码,而是DLL中相应函数代码的地址,从而节省了内存资源。DLL和LIB文件必须随
应用程序一起发行,否则应用程序会产生错误
MT和MD区别:
(1)MD,表示运行时库由操作系统提供一个DLL,程序里不集成。程序就不需要静态链接运行时库,可以减小软件的大小,所有的模块都采用/MD,使用的是同一
个堆,不存在A堆申请,B堆释放的问题;但用户机器可能缺少我们编译时使用的动态运行时库。
(2)MT,表示运行时库由程序集成,程序不再需要操作系统提供运行时库DLL。有些系统可能没有程序所需要版本的运行时库,程序必须把运行时库静态链接上,
减少模块对外界的依赖
要注意的问题:
(1)选择MT需要解决的堆空间释放问题,不同的模块各自有一份C运行时库代码、或者根本没有C运行时库,导致了各个模块会有各自的堆。如果在A堆中申请空间
,到B堆中释放就会有崩溃,在模块A申请的空间,必须在模块A中释放。
(2)选择MD需要注意多个模块使用不同版本运行时库的问题,多个dll被一个exe LoadLibrary加载,如果这些dll使用的运行时库是不同的,那么可能出现加载失
败,原因可能是旧版本的运行时库已经在了,而某个dll它需要的是新版本的运行时库,旧版本不符合要求。
8.简述windows消息循环机制
当用户有操作(鼠标,键盘等)时,系统会将这些操作转化为消息,放在系统消息队列中。每个打开的进程系统都为其维护了一个消息队列,系统会将这些消息拷贝到对应
进程的消息队列中,而应用程序会循环从消息队列中取出来消息,完成对应的操作
9.Peekmessage和Getmessage的区别
GetMessage:从系统获取消息,将消息从系统中移除,属于阻塞函数。当系统无消息时,GetMessage会等待下一条消息。
PeekMesssge:以查看的方式从系统中获取消息,可以不将消息从系统中移除,是非阻塞函数;当系统无消息时,返回FALSE,继续执行后续代码
10.线程同步的同步对象有哪些,他们之间有什么区别
临界区、互斥量、信号量、事件;临界区只能同一进程中线程使用,不能跨进程使用,事件,互斥量,信号量都是内核
对象,都可以跨进程使用;临界区和互斥量都只允许一个进程访问共享资源;信号量允许多个线程同时使用共享资源;
事件机制,则允许一个线程在处理完一个任务后,主动唤醒另外一个线程执行任务。
11.编程题:矩阵乘法。给定每个矩阵的行和列及乘的顺序,输出乘法的次数。第一个矩阵为A,第二个矩阵为B,以此类推
示例: 输入描述: 3 50 10 10 20 20 5 (A(BC)) 输出描述: 3500
#include<bits/stdc++.h> #include<iostream> #include<vector> using namespace std; int main(){ int n; while (cin >> n){ vector<vector<int>>data(n, vector<int>(2)); for (int i = 0; i < n; i++) cin >> data[i][0] >> data[i][1]; string str; while (cin >> str){ vector<vector<int>>s; int res = 0; for (int i = 0; i < str.size(); i++){ if (str[i] == ')'){ while (s.back()[0] != 0){ int r = s.back()[1]; int mid = s.back()[0]; s.pop_back(); int l = s.back()[0]; s.pop_back(); res += l*mid*r; vector<int>t(2); t[0] = l; t[1] = r; if (s.back()[0] == 0){ s.pop_back(); s.push_back(t); break; } s.push_back(t); } } else if (str[i] == '('){ vector<int>t(2,0); s.push_back(t); } else{ vector<int>t(2); t[0] = data[str[i] - 'A'][0]; t[1] = data[str[i] - 'A'][1]; s.push_back(t); } } cout << res << endl; } } return 0; }