2019暑期C/C++实习生面试笔试题,虽然简单基础,但正确率只有60%

当时笔试做题的时候,面试官说半个小时以后来拿卷子,我趁机拍了一点,现在回过头再做一遍,也算是一个复习和提高,上图,第三大题没有拍全,等会后面补上。2019暑期C/C++实习生面试笔试题,虽然简单基础,但正确率只有60%_第1张图片

第一题较简单,需要注意的只有float变量与零值的比较可能会比较坑,其他的都是常规,float变量与零值的if比较应该是:

const EPSINON=0.00001; 

if((x>=-EPSINON)&&(x<=EPSINON));     //为什么是0.00001,可以具体查看float变量的精度和有效位数的介绍

 

第二题除了前三个会,其他都是蒙的,查了资料以后总结如下,发现自己蒙错了最后一题,但最后一题不应该错的。

sizeof是一个操作符(operator),其作用是返回一个对象或类型所占的内存字节数。

1.char str[]="Hello";      sizeof(str)=6;   

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

注意:1)当字符数组表示字符串时,其sizeof值将’/0’计算进去。

            2)当数组为形参时,其sizeof值相当于指针的sizeof值。 

2.char *p = str;             sizeof(p)=4;   

指针是用来记录另一个对象的地址,所以指针的内存大小当然就等于计算机内部地址总线的宽度。

在32位计算机中,一个指针变量的返回值必定是4。

指针变量的sizeof值与指针所指的对象没有任何关系。

3.int n = 10;                 sizeof(n)=4;     //int类型占用的字节数依系统而定,题目说是Windows NT 32,那应该是4

4.void Func(char str[100]);   sizeof(str)=4;   //当数组为形参时,其sizeof值相当于指针的sizeof值。 

5.void *p=malloc(100);            sizeof(p)=4;  //此时p为指针类型,在32位系统下占4个字节

 

第三题,列出如下:
1.说明#ifndef #define #endif的作用。

这个会c的人应该都懂,作用是避免重复包含头文件,因为只有在第一次没有包含该头文件时会执行#define和#endif之间的代码(有效代码,函数声明,类声明等),之后有文件想再次包含该头文件时,#ifndef为假,直接endif,不再次包含。

2.#include 和#include "filename.h"有什么区别?

用#include表示预处理编译器直接在C++系统目录中查找要包含的头文件filename.h。

用#include“filename.h”的表示预编译器首先在当前被编译文件所在目录中进行搜索filename.h,若找不到,再去C++系统目录中查找。就是查找的路径不同了。

3.说明const的作用。

说实话,考这题之前我还知道这个const是干嘛的,可这一问,我却都想不起来了。

const的作用:(1)可以避免由于无意间修改数据而导致编程出现错误;(2)可以节省空间,避免不必要的内存分配,原因是例如:

#define PI 3.14159 //常量宏const double Pi=3.14159; //此时并未将Pi放入RAM中 ......double i=Pi; //此时为Pi分配内存,以后不再分配!double I=PI; //编译期间进行宏替换,分配内存double j=Pi; //没有内存分配double J=PI; //再进行宏替换,又一次分配内存!const定义常量从汇编的角度来看,只是给出了对应的内存地址,而不是像#define一样给出的是立即数,所以,const定义的常量在程序运行过程中只有一份拷贝,而#define定义的常量在内存中有若干份拷贝。 

(3)提高了效率。编译器通常不为普通const常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率也很高。

4.当C++程序要用C语言方式编译的代码时,为什么要加extern C?

可参见https://www.cnblogs.com/daocaorenblog/p/5310492.html,具体我也没怎么回答上来,有空看看

5.说明下面两个for循环的优缺点:
for (int i = 0;i < n;i++)
{
    if (condition)
       dosomething();
    else
       dootherthing();
}

{
    if (condition)
    {
        for (int i = 0;i < n;i++)
            dosomething();
    }
    else
    {
        for (int i = 0;i < n;i++)
            dootherthing();
    }
}

前者:
优点:程序简洁
条件判断出现在For里面,意味着,即使我在dosomething()或dootherthing()这2个函数中改变了condition的值,For循环也能正确执行我的意图,因为它在每次循环中都会重新检测conditon的值并针对condition的值做不同动作,所谓以不变应万变,这是难能可贵的.   
缺点:多执行了N-1次逻辑判断,并且打断了循环“流水线”作业,使得编译器不能对循环进行优化处理,降低了效率。
如果condition一直未曾改变,我们可怜的if必须每次循环都判断一下condition的真假.牺牲了运行时效率.
后者:
优点:循环的效率高。只进行一次判断,运行时效率高.适合那种condition的值不会改变的情况.
缺点:由于只在一开始进行一次判断,所以失去的改变condition的值的机会,也就是说,即使我在dosomething()中改变了condition的值为false,这个程序也不会改变它的判断,它依然执行着dosomething()的循环.我们不能随时更换我们需要进行的动作。这是牺牲了弹性。

n较大时,建议采用后面这种写法,由于前者老要进行逻辑判断,打断了循环“流水线”作业,使得编译器不能对循环进行优化处理,降低了效率。

6.重写函数char *strcpy(char *dest, char *src)。

c库函数内的strcpy函数为:

char *strcpy(char *strDestination, const char *strSource);
{
    assert((strDestination!=NULL) && (strSource !=NULL));   //断言,当其中任有一个为NULL时,程序终止,打印错误信息
    char *address = strDestination; 
    while( (*strDestination++ = * strSource++) != '/0') NULL ;
    return address ; 
}

自己写的:

char *strcpy(char *dest, char *src)
{
    if (dest == NULL || src == NULL)
        return NULL;
    char *newcopy = dest;
    while ((*dest++ = *src++) != '\0');  //只要源字符串还没有到\0,就继续复制
    return newcopy;

}

面试官问的问题是while中*和++运算符的优先级,不会,乱回答的。还有为什么返回的是在函数内定义的指针变量

(1)*和++的优先级和结合性:*作为 指针取值 运算符,级别同 ++(自增)一样。

优先级是用来标识运算符在表达式中的运算顺序的,在求解表达式的值的时候,总是先按运算符的优先次序由高到低进行操作。但是,当一个运算对象两侧的运算符的优先级别相同时,则按运算符的结合性来确定表达式的运算顺序。

结合性是指同一优先级的运算符在表达式中操作的组织方向,即:当一个运算对象两侧的运算符的优先级别相同时,运算对象与运算符的结合顺序。

最容易搞混的莫过于运算符优先级处于第二级别的了,尤其是当 * 和 ++ 用在一起时: 

è¿ç®ç¬¦ä¼å级åç»åæ§

这里应该是优先级相同,按照从右到左的顺序结合,先进行P++,又因为是后加加,故p++执行后得到的还是p,然后取*p,*p++整句代码执行完后,执行p=p+1。从这些分析可以得出上面的while内的运算顺序。

(2)为什么返回函数内的指针变量:newcopy和dest指向的是同一内存。

返回strDest的原始值使函数能够支持链式表达式,增加了函数的“附加值”。同样功能的函数,如果能合理地提高的可用性,自然就更加理想。

链式表达式的形式如:

int iLength=strlen(strcpy(strA,strB));

又如:

char * strA=strcpy(new char[10],strB);

 

 

 

你可能感兴趣的:(实习生面试笔试题总结)