技术交流QQ群:1027579432,欢迎你的加入!

  • Q1.char p1[] = “Tencent”, void*p2 = malloc((10)在32位机器上sizeof(p1)和sizeof(p2)对应的值是?
  • A:对于一个数组, sizeof 返回这个数组所有元素占的总空间。而 strlen 不区分是数组还是指针,就读到 \0 为止返回长度。所以sizeof(p1)=8;void *p2=malloc(10),void* 是空指针,可以指向任意类型,不能操作void*所指对象,而32位机器指针占4位,所以sizeof(p2)=4
  • Q2.下面程序段的输出结果是
char *p1 = ”123”, *p2 = ”ABC”, str[50] = “xyz”;
strcpy(str + 2, strcat(p1, p2));
printf(“%s\n”, str);
  • A:出错!p1和p2都指向常量字符串,在常量区,所以不能对其进行操作;改为数组即可,但是用字符串初始化数组时要记得将数组长度加1,因为字符串默认的末尾有一个‘\0’;第二点要注意的是,strcat函数的p1要有足够的空间来容纳p1和p2连接后的串长。修改代码如下:
char p1[7] = "123";
char p2[] = "ABC";
char str[50] = "xyz";
strcpy(str + 2, strcat(p1, p2));
printf("%s\n", str);
  • Q3. 下列程序的输出结果是
void main()
{
printf("s1=│%15s│s2=│%-5s│","chinabeijing","chi");
}
  • A: s1=│chinabeijing□□□│s2=│chi│,解释:%15s表示输出占15个空格的位置,并且右对齐,左边多余的位置补空格,因为“chinabeijing”包含12个字符,所以输出时,左边要补上3个空格%-5s表示输出占5个空格的位置,并且左对齐,右边多余的位置补空格,因为”chi”包含3个字符,所以输出时,右边要补上2个空格。
  • Q4. 在32位大端模式处理器上变量b等于()?
unsigned int a= 0x1234; unsigned char b=*(unsigned char *)&a;
  • A: unsigned int a= 0x1234; 其中int是4字节, 大端存储(高位存储在低地址) ,补齐16进制表示为: 0x00 00 12 34, unsigned char b=*(unsigned char *)&a; 由于大端存储, 所以上述int a变量的最低地址存储的是 十六进制表示中最左边的1字节, 为0x00.若处理器为小端存储(低地址存储低位) 模式,则b的值为0x34
  • Q5. 假定CSomething是一个类,执行下面这些语句之后,内存里创建了6个CSomething对象?
CSomething a();   //没有创建对象,这里不是使用默认构造函数,而是定义了一个函数
CSomething b(2);  // 使用一个参数的构造函数,创建了1个对象
CSomething c[3];  // 使用无参构造函数,创建了3个对象
CSomething &ra = b;  // ra引用b,没有创建新对象
CSomething d=b;  // 使用拷贝构造函数,创建了1个新的对象d
CSomething *pA = c;  // 创建指针,指向对象c,没有构造新对象
CSomething *p = new CSomething(4);  // 新建1个对象
  • Q6:若有以下定义和赋值语句,则与&s[i][j]等价的是()
int s[2][3] = {0}, (*p)[3], i, j;
p = s;
i = j = 1;
  • A6:int s[2][3]是一个二维数组,int (*p)[3]是一个数组指针;与s[i][j]等价的是*(*(p+i)+j)、(*(p+i))[j]、*(*p[i]+j);与&s[i][j]等价的是*(p+i)+j
  • Q6.以下代码打印的结果是(假设运行在 64 位计算机上):
struct st_t {
    int status;  // 占用8个(后面的4个为对齐位)
    short *pdata; //占用8个
    char errstr[32];  //占用32个
};
st_t st[16];
char *p=(char *)(st[2].esstr+32);
printf(“%d”,(p-(char *)(st)));
  • A6:答案:144.解释:64 位计算机上,默认是8字节对齐。char *p=(char *)(st[2].esstr+32),p实际指向了st[3]。则p-(char *)(st)),即为&st[3]-&st[0],占用空间为3个结构体的大小,即3*48=144

1.静态成员的特点

  • 1.static数据成员在类的内部声明,但只能在类的外部定义,在类的外部不能指定static,在类的定义时候进行初始化;
  • 2.static数据成员只能在类的外部进行初始化(特例:当整型const static数据成员被常量表达式初始化时,就可以在类的内部进行初始化,但还需要在外部进行定义)。
  • 3.static数据成员可以是该成员所属的类类型,而非static数据成员只能自身类的引用或者指针。
  • 4.static数据成员可以用作类成员函数的默认实参。
  • 5.static数据成员的值可以改变。

2.静态成员和非静态成员的区别

  • 1.静态变量使用static修饰符进行声明,在类被实例化时创建,通过类和对象都可以进行访问;
  • 2.不带有static修饰符声明的变量称做非静态变量,在对象被实例化时创建,通过对象访问;
    1. 一个类的所有实例的同一静态变量都是同一个值,同一个类的不同实例的同一非静态变量可以是不同的值。
  • 4.静态函数的实现里不能使用非静态成员,如非静态变量、非静态函数等。

3.静态成员函数的特点

  • 1.static成员函数没有this形参,它可以访问所属类的static 成员,但不能访问非static成员。
  • 2.static成员函数既可以在类的内部定义,也可以在类的外部定义,在外部定义时,不能重复指定static保留字。
  • 3.static成员函数不能声明为虚函数,不能实现动态绑定
  • 4.static成员函数不能声明为const,因为const是针对this是不是const而言的
  • 5.构造函数、析构函数不能为静态函数

4.静态链接库和动态链接库

  • 静态链接库的优点:
    • 代码装载速度快,执行速度略比动态链接库快;
    • 只需保证在开发者的计算机中有正确的.LIB文件,在以二进制形式发布程序时不需考虑在用户的计算机上.LIB文件是否存在及版本问题,可避免DLL地狱等问题。
  • 动态链接库的优点:
    • 更加节省内存并减少页面交换
    • DLL文件与EXE文件独立,只要输出接口不变(即名称、参数、返回值类型和调用约定不变),更换DLL文件不会对EXE文件造成任何影响,因而极大地提高了可维护性和可扩展性;
    • 不同编程语言编写的程序只要按照函数调用约定就可以调用同一个DLL函数;
    • 适用于大规模的软件开发,使开发过程独立、耦合度小,便于不同开发者和开发组织之间进行开发和测试。
  • 不足之处:
    • 使用静态链接生成的可执行文件体积较大,包含相同的公共代码,造成浪费;
    • 使用动态链接库的应用程序不是自完备的,它依赖的DLL模块也要存在,如果使用载入时动态链接,程序启动时发现DLL不存在,系统将终止程序并给出错误信息。而使用运行时动态链接,系统不会终止,但由于DLL中的导出函数不可用,程序会加载失败;速度比静态链接慢。当某个模块更新后,如果新模块与旧的模块不兼容,那么那些需要该模块才能运行的软件,统统撕掉。这在早期Windows中很常见。

5.malloc与new的对比

  • new建立的是一个对象,malloc分配的是一块内存
  • new初始化对象,调用对象的构造函数,对应的delete调用相应的析构函数,malloc仅仅分配内存,free仅仅回收内存。
  • new和malloc都可用于申请动态内存,new是一个操作符,malloc是一个函数。

6.关键路径的求法

  • 一个事件的最迟开始时间:以该事件为头的弧的活动最迟开始时间与该活动的持续时间的差
  • 一个事件的最早开始时间:以该事件为尾的弧的活动最早开始时间相同。

7.C++中的接口

  • 接口:只包含纯虚函数的抽象类

8.容易混淆的运算符优先级顺序

  • -> . ++ -- *

9.排序算法对比

  • 基于比较的常用排序算法:插入排序、冒泡排序、选择排序、希尔排序、快速排序、堆排序、归并排序。
  • 非基于比较的排序算法:基数排序、桶排序

10.内联函数与宏的区别

  • 内联函数在运行时可调试,而宏定义不可以
  • 编译器会对内联函数的参数类型做安全检查或自动类型转换(同普通函数),而宏定义则不会
  • 内联函数可以访问类的成员变量,宏定义则不能
  • 在类中声明同时定义的成员函数,自动转化为内联函数

11.关于纯虚函数和抽象类的描述

  • 纯虚函数是一种特殊的虚函数
  • 抽象类是指具有纯虚函数的类
  • 抽象类只能作为基类来使用,其纯虚函数的实现由派生类给出。
  • 如果基类有纯虚函数,而其派生类中没有重写改函数,则其依然为纯虚函数,这个派生类依然是个抽象类。

12.广义表的长度与深度

  • 长度为第一层的元素个数
  • 深度是子表最大的嵌套次数

13.B树的介绍

  • 各结点的关键字和可以拥有的子结点数都有限制,每个结点至多可以拥有m个子结点。
  • 根结点至少有2个子结点,除非根结点为叶子结点。非根结点至少有[m/2]([],向上取整)个子结点,关键字个数为[m/2]-1~m-1。
  • 所有的叶子节点在同一层
  • 根结点中关键字的个数为1~m-1,比结点数目少一个

14.在有向图的邻接表表示中,下面哪一种操作最费时间

  • 在邻接表结构中,求顶点的出度容易,入度困难。逆邻接表中,求顶点的入度容易,出度困难。

15.有向图G中有n个顶点,e条边,采用邻接表存储,若采用DFS/BFS方式遍历其时间复杂度

  • 邻接矩阵-O(n^2)
  • 邻接表-O(n+e)