2.15 C++专项练习 错题复盘

定义宏#define DECLARE(name, type) type name##_##type##_type,
则DECLARE(val, int)替换结果为()

正确答案: A   你的答案: B (错误)

int val_int_type
int val_int_int
int name_int_int
int name_int_name


解析:##相当于强制分割,所以分成了 name,_,type,_type 所以答案显而易见了


以下数字在表示为double(8字节的双精度浮点数)时存在舍入误差的有()。

正确答案: A B C   你的答案: A B (错误)

2的平方根
10的30次方
0.1
0.5
100

解析:小数看是否有误差的时候就是化为二进制,如果能够化开那就可以,如果不行的话那么就要舍入




下列运算符重载函数中,属于友元函数的是(      )

正确答案: B C D   你的答案: C D (错误)

Base operator+(Base);
Base operator--(Base);
Base operator&&(Base, Base);
Base operator++(Base,int);


解析:看出是否是友元的话主要是看是否能够调用this指针,这样就会少传进一个参数,




下面关于"指针"的描述不正确的是()

正确答案: A   你的答案: C (错误)

当使用free释放掉一个指针内容后,指针变量的值被置为NULL
32位系统下任何类型指针的长度都是4个字节
指针的数据类型声明的是指针实际指向内容的数据类型
野指针是指向未分配或者已经释放的内存地址

解析:当free释放内存之后,指针还指向原来的那块地址,需要我们设置 p = NULL;如果不手动设置 p = NULL,此时P就变成了野指针



C++中关于堆和栈的说法,哪个是错误的:

正确答案: C   你的答案: D (错误)

堆的大小仅受操作系统的限制,栈的大小一般一般较小
在堆上频繁的调用new/delete容易产生内存碎片,栈没有这个问题
堆和栈都可以静态分配
堆和栈都可以动态分配
解析:选C,静态分配是指在编译阶段就能确定大小,由编译器进行分配,堆不可以进行静态分配,堆的申请都是在执行过程中进行的。
A,堆和栈的大小都可以设置,栈一般只有几KB。
B,堆在动态分配时,要申请连续的内存空间,释放后会产生碎片。
D,堆是使用malloc()、calloc()、realloc()等函数动态分配的,而使用alloca()函数可以动态分配栈的内存空间,释放的时候由编译器自己释放。



以下关于内联函数,说法正确的是:

正确答案: A B C   你的答案: A C (错误)

一般用于加快程序执行速度
可能减小可执行文件大小
可能增加可执行文件大小
以上说法都不正确
解析:AC选项不说了,直接说B选项。若这个函数被调用了一次,那么内联直接被插入到函数调用出,就直接没有了这个函数符号了,若加上优化,这一句代码可能会被优化没有,所以,可执行文件可能会减少。



Math.round(11.5) 等于多少 (). Math.round(-11.5) 等于多少 (  ).

正确答案: C   你的答案: A (错误)

11 ,-11
11 ,-12
12 ,-11
12 ,-12
解析:floor : 意为地板,指向下取整,返回不大于它的最大整数 ceil : 意为天花板,指向上取整,返回不小于它的最小整数 round : 意为大约,表示“四舍五入”,
而四舍五入是往大数方向入。Math.round(11.5)的结果为12,Math.round(-11.5)的结果为-11而不是-12。


下面的程序输出可能是
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Printer{
     public :
         Printer(std::string name) {std::cout << name;}
};
class Container{
     public :
         Container() : b( "b" ), a( "a" ) {}
     Printer a;
     Printer b;
};
int main(){
     Container c;
     return 0;
}

正确答案: C   你的答案: A (错误)

可能是 "ab" 或 "ba"。 依赖于具体的实现
一直都是 "ba"
一直都是 "ab"


解析:只和结构体定义的时候变量顺序有关



如下代码一共创建多少个进程(包含主进程):
1
2
3
4
5
int main( int argc,  char * argv[]) {
fork();
fork() && fork() && fork();
fork() || fork();
}

正确答案: D   你的答案: B (错误)

15
18
21
24


解析:首先需要明白的是fork()生成1个子进程,fork()之后有两个进程处于执行状态。因此执行完第一个fork(),生成的进程数是1(main)+1(子进程)看第二行的fork() && fork() && fork(),
执行完第一个fork(),父进程返回非0,子进程返回0,子进程后面的fork()均不会执行,此时产生了1个子进程,那么三个fork()就产生了3个子进程(注意,这是1个进程产生的),
因此执行完第二行,产生了6个子进程,系统中一共有8个进程在执行,要是不明白的自己画个二叉树就清楚了。在看第三行,fork() || fork(),原理和第二行相同,只是只有子进程才能继续,
父进程只能执行第一个fork(),执行这一行每个进程可以产生两个子进程,也就是一***生2 * 8 = 16个子进程所以答案就是 2 + 6 + 16 = 24



请指出以下程序的错误:
 
void  GetMemory( char **p,  int num)
{
     if (NULL==p && num<= 0 ) //1
 
         return ;
     *p=( char *)malloc(num);
     return ;
}
void main( void ){
     char *str=NULL;
     GetMemory(&str, 80 );  //2
     if (NULL!=str){
         strcpy(&str, "hello" );  //3
         printf(str);
     }
     return true //4
}
 

正确答案: A C D   你的答案: C D (错误)

1
2
3
4


解析: if(NULL==p && num<=0)//1  应该为 if(NULL==p || num<=0) strcpy(&str,"hello"); //3   应为 strcpy(str,"hello"); return true; //4   与void冲突







下面这个程序执行后会有什么错误或者效果:
#define MAX  255
int main()
{
      unsigned  char A[MAX], i;
      for (i =  0 ; i <= MAX; i++)
          A[i] = i;
}

正确答案: A B   你的答案: A (错误)

数组越界
死循环
栈溢出
内存泄露



解析:这个问题能将面试者的能力分为三类;
一:没错。。。那么说明面试者的C语言基础能力不行;
二:有个错,是哪个i<=MAX; 数组下标越界。。嗯,还行;
三:死循环,C的基本功很强。。达到了该题的测试目的;

分析了一下: 
出现了两个问题; 
一:下标越界可以说是个问题,但不是问题的本质; 当i=MAX;即i=MAX是,对数组来说,255是越界了,那如果我把数组下标改了是不是就对了呢?比如说如下:
#include <stdio.h>
#define MAX 255
int main() { 
unsigned char a[256],i;//这里改成256是不是就对了呢? 还是不对;
for(i=0;i< =MAX;i++)
a[i]=i;
for(i=0;i< =MAX;i++) 
printf("%d ",a[i]); 
}   
其实越界了编译还是能通过的,因为编译器不检查越界问题;

问题二: 上例还是错的,原因在于unsigned char 这个数据类型,它占了 8位,表示范围是 0~255(00000000~11111111,八位); 当改成256后,虽说看似数组下标没越界,但是当i=255; i++ ;因为 i本身是unsigned char类型,占8位,所以此时i+1变成了100000000 9位,又因为i只能占8位,所以舍掉了最高位,此时的i值又变成00000000了,即就是0;然后就成了死循环了。。。

猜你喜欢

转载自www.cnblogs.com/Lis-/p/12312818.html