C/C++工程师综合练习卷

1 补充下面函数代码:
如果两段内存重叠,用memcpy函数可能会导致行为未定义。 而memmove函数能够避免这种问题,下面是一种实现方式,请补充代码。

#include <iostream>
using namespace std;
void* memmove(void* str1,const void* str2,size_t n)
{
    char* pStr1= (char*) str1;
    const char* pStr2=(const char*)str2;
    if  ( ) {
        for(size_t i=0;i!=n;++i){
            *(pStr1++)=*(pStr2++);
        }
    }
    else{
        pStr1+=n-1;
        pStr2+=n-1;
        for(size_t i=0;i!=n;++i){
            *(pStr1--)=*(pStr2--);
        }
    }
    return ( );
}
pStr1< pStr2 pStr1
pStr1+n < pStr2 pStr2
pStr1+n < pStr2 || pStr2+n<pStr1 pStr2
pStr2+n<pStr1 pStr1

2 int x[6][4],(*p)[4]: p=x;   则*(p+2)指向哪里?
x[0][1]
x[0][2]
x[1][0]
x[2][0]

3 下面有关C++中为什么用模板类的原因,描述错误的是?
可用来创建动态增长和减小的数据结构
它是类型无关的,因此具有很高的可复用性
它运行时检查数据类型,保证了类型安全
它是平台无关的,可移植性

4
int func(int a)
{
    int b;
    switch (a)
    {
        case 1: b = 30;
        case 2: b = 20;
        case 3: b = 16;
        default: b = 0;
    }
    return b;
}
则func(1) = ?
30
20
16
0

5
class A
{
        int a;
        short b;
        int c;
        char d;
};
class B
{
        double a;
        short b;
        int c;
        char d;
};

在32位机器上用gcc编译以上代码,求sizeof(A),sizeof(B)分别是多少。
12 16
12 12
16 24
16 20
//根据以下条件进行计算:
1、  结构体的大小等于结构体内最大成员大小的整数倍
2、  结构体内的成员的首地址相对于结构体首地址的偏移量是其类型大小的整数倍,比如说double型成员相对于结构体的首地址的地址偏移量应该是8的倍数。
3、  为了满足规则1和2编译器会在结构体成员之后进行字节填充!


6 下面有关继承、多态、组合的描述,说法错误的是?
封装,把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏
继承可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展
隐藏是指派生类中的函数把基类中相同名字的函数屏蔽掉了
覆盖是指不同的函数使用相同的函数名,但是函数的参数个数或类型不
//重载

7 下面有关c++线程安全,说法错误的是?
线程安全问题都是由全局变量及静态变量引起的
若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则的话就可能影响线程安全
c++标准库里面的string保证是线程安全的
POSIX线程标准要求C标准库中的大多数函数具备线程安全性

8
以下程序的输出是
class Base {
    public:
    Base(int j): i(j)  {}
    virtual~Base() {}
    void func1() {
        i *= 10;
        func2();
    }
    int getValue() {
        return  i;
    }
    protected:
    virtual void func2() {
        i++;
    }
    protected:
    int i;
};
class Child: public Base {
    public:
    Child(int j): Base(j) {}
    void func1() {
        i *= 100;
        func2();
    }
    protected:
    void func2() {
        i += 2;
    }
};
int main() {
    Base * pb = new Child(1);
    pb->func1();
    cout << pb->getValue() << endl; delete pb; } 
11
101
12
102
//
Base * pb = new Child(1), 首先创建子类对象,初始化为1,但是pb是BASE类型;
func1()不是虚函数,所以pb->func1()执行的是基类的func1函数,i= 10,然后调用func2()函数;
这里的func2是虚函数,要往下派生类寻找,找到后执行派生类中的func2(),此时,i = 12;
最后执行pb->getValue(),结果为12

9 下面对静态数据成员的描述中,正确的是?
静态数据成员可以在类体内进行初始化
静态数据成员不可以被类的对象调用
静态数据成员不受private控制符的作用
静态数据成员可以直接用类名调用

10 #include<file.h> 与 #include "file.h"的区别?
前者首先从当前工作路径搜寻并引用file.h,而后者首先从Standard Library的路径寻找和引用file.h
前者首先从Standard Library的路径寻找和引用file.h,而后者首先从当前工作路径搜寻并引用file.h
两者都是首先从Standard Library的路径寻找和引用file.h
两者都是首先从当前工作路径搜寻并引用file.h

11
下面代码的输出是什么?
class A  
{  
public:  
    A()  {     }  
    ~A() {    cout<<"~A"<<endl;   }  
};  
  
class B:public A  
{  
    public:  
        B(A &a):_a(a)  
        {  
            
        }  
        ~B()  
        {  
            cout<<"~B"<<endl;  
        }  
    private:  
        A _a;  
    };  
      
int main(void)  
 {  
        A a;       //很简单,定义a的时候调用了一次构造函数  
        B b(a); 
}
~B
~B~A
~B~A~A
~B~A~A~A
//
首先 A a;这个调用A的默认构造函数,B b(a); 因为A &a,形参为引用,不需要调用基类复制构造函数(其实基类也没写);_a(a)首先创建对象_a,调用基类A的默认构造函数,然后调用基类复制构造函数,把a对象赋给_a,结束之后调用B的析构函数,输出~B;然后调用基类A的析构函数撤销复制构造函数,输出~A;调用基类A的析构函数撤销_a,输出~A;最后调用基类A的析构函数撤销一开始创建的A a,输出~A

12 以下程序的结果?
void foo(int *a, int *b)
{
    *a = *a + *b;
    *b = *a - *b;
    *a = *a - *b;
}
void main()
{
    int a = 1, b = 2, c = 3;
    foo(&a, &b);
    foo(&b, &c);
    foo(&c, &a);
    printf("%d, %d, %d", a, b, c);
}
1,2,3
1,3,2
2,1,3
3,2,1

13
下列一段C++代码的输出是?
#include "stdio.h"
class Base
 {
 public:
     int Bar(char x)
     {
         return (int)(x);
     }
     virtual int Bar(int x)
     {
         return (2 * x);
     }
 };
 class Derived : public Base
 {
 public:
     int Bar(char x)
     {
         return (int)(-x);
     }
     int Bar(int x)
     {
         return (x / 2);
     }
 };
 int main(void)
 {
     Derived Obj;
     Base *pObj = &Obj;
     printf("%d,", pObj->Bar((char)(100)));
     printf("%d,", pObj->Bar(100));
 }
100,-100
100,50
200,-100
200,50

14 C++类体系中,不能被派生类继承的有?
构造函数
静态成员函数
非静态成员函数
赋值操作函数
//构造函数是不能被继承的,但是可以被调用,如果父类重新定义了构造函数,也就是没有了默认的构造函数,子类创建自己的构造函数的时候必须显式的调用父类的构造函数。

15 下面有关malloc和new,说法错误的是? 
new 建立的是一个对象, malloc分配的是一块内存.
new 初始化对象,调用对象的构造函数,对应的delete调用相应的析构函数,malloc仅仅分配内存,free仅仅回收内存
new和malloc都是保留字,不需要头文件支持
new和malloc都可用于申请动态内存和释放内存,new是一个操作符,malloc是是一个函数
//malloc使用需要stdlib.h头

16 下面有关类的静态成员和非静态成员,说法错误的是? 
静态成员存在于内存,非静态成员需要实例化才会分配内存
非静态成员可以直接访问类中静态的成员
静态成员能访问非静态的成员
非静态成员的生存期决定于该类的生存期,而静态成员则不存在生存期的概念
//静态成员存在于内存,非静态成员需要实例化才会分配内存,所以静态成员函数不能访问非静态的成员。因为静态成员存在于内存,所以非静态成员函数可以直接访问类中静态的成员

17
下列代码的输出为:
class CParent 
{
    public: virtual void Intro()
    {
        printf( "I'm a Parent, " ); Hobby();
    }
    virtual void Hobby()
    {
        printf( "I like football!" );
    }
}; 
class CChild : public CParent { 
    public: virtual void Intro()
    {
        printf( "I'm a Child, " ); Hobby();
    }
    virtual void Hobby()
    {
       printf( "I like basketball!\n" );
    }
}; 
int main( void )
{
    CChild *pChild = new CChild(); 
    CParent *pParent = (CParent *) pChild; 
    pParent->Intro(); 
    return(0);
}
I'm a Parent, I like football!
I'm a Parent, I like basketball!
I'm a Child, I like basketball!
I'm a Child, I like football!

18
在32位小端的机器上,如下代码输出时什么:
char array[12] = {0x01 , 0x02 , 0x03 , 0x04 , 0x05 , 0x06 , 0x07 , 0x08};     
 short *pshort = (short *)array;     
 int *pint = (int *)array;     
 int64 *pint64 = (int64 *)array;     
 printf("0x%x , 0x%x , 0x%x , 0x%x", *pshort , *(pshort+2) , *pint64 , *(pint+2));
0x201 , 0x403 , 0x807060504030201 , 0x0
0x201 , 0x605 , 0x807060504030201 , 0x0
0x201 , 0x605 , 0x4030201 , 0x8070605
0x102 , 0x506 , 0x102030405060708 , 0x0

19 switch(c)语句中,c不可以是什么类型()
int
long
char
float

20 头文件中的 ifndef/define/endif 干什么用?
定义常量
标记为特殊的头文件
防止头文件被重复引用
注释头文件

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值