C/C++ 工程师能力评估试题

C/C++工程师能力评估


1 关于new的讨论
int *p1 = new int[10]; //p1申请的空间里的值是随机值
int *p2 = new int[10] ();//p2申请的空间里的值初始化为0

int *p2 = new int[10] (); // 申请了空间,而且进行了初始化
int *p1 = new int[10] ; // 只申请空间,没有进行初始化

关于new的讨论见:

http://blog.csdn.net/luanqibaazao/article/details/77823442


2 随机等概率输出m个不重复的数
void knuth(int n,int m)
{
  srand((unsigned int)time(0));
  for(int i = 0;i<n;i++)
  {
    if(rand()%(n-i)<m)
    {
      cout<<i<<endl;
      m--;
    }
  }
}

等概率:http://blog.csdn.net/luanqibaazao/article/details/77756728


3 分解质因子

n从2开始,保证为质因子

void prim(int m, int n)
 {
     if (m >= n)
     {
         while( m%n ) n++;
         m=m/n;
         prim(m, n);
         cout << n << endl;
     }
}

http://blog.csdn.net/luanqibaazao/article/details/77803231


4 enum 类型初值问题

enum <枚举类型名> {枚举值表} <枚举变量>;
例如:
enum string {
x1,
x2,
x3=10,
x4,
x5,
} x;
函数外部访问x等于什么?

全局变量的默认初始化为0

enum相关:
http://blog.csdn.net/luanqibaazao/article/details/77824856


5 指针变量的加减运算
unsigned char *p1;
unsigned long *p2;
p1=(unsigned char *)0x801000;
p2=(unsigned long *)0x810000;

问:

p1+5= ?
p2+5= ?

答:

801005   810014

解析:
指针型变量 p+1 表示指向下一个元素的地址
p1指向字符型,一次移动一个字符型,1个字节;p1+5后移5个字节,16进制表示为5;
p2指向长整型,一次移动一个长整型,4个字节,p2+5后移20字节,16进制表示为14。

0x1101 // 十六进制
01101  // 八进制
1101   // 十进制

6 数组名作为函数参数传递

数组名作为函数参数传递时,数组名退化成指针,传递过去的其实是数组的首地址

void example(char acWelcome[]){
    printf("%d",sizeof(acWelcome));
    return;
}

答: 4


7 关于虚函数和函数重载的叙述

(1)虚函数不是类的成员函数 (x)
(2)虚函数实现了C++的多态性 (√)
(3)函数重载允许非成员函数,而虚函数则不行 (√)
(4)函数重载的调用根据参数的个数、序列来确定,而虚函数依据对象确定 (√)

虚函数是类的成员函数,A说法是不正确的;

多态性分为编译时多态性和运行时多态性:
编译时多态性通过静态编联完成,例如函数重载,运算符重载;
运行时多态性则是动态编联完成,主要通过虚函数来实现;

虚函数和函数重载都实现了C++的多态性,但表现形式不一样,函数重载调用根据参数个数、参数类型等进行区分,而虚函数则是根据动态联编来确定调用什么,故BD说法正确

函数重载可以是类的成员函数 在类外声明或定义的函数同样可以对其进行重载
比如:

int fun(int a);
int fun(int a, int b);

这就是非成员重载,虚函数必须是成员函数了,否则就失效了, 所以C对

重载的调用主要根据参数个数,参数类型,参数顺序来确定, 函数重载是忽略返回值的


8 访问越界

伪代码片:

while(page.taglst[i] == "<br>" && i < taglen) {
              ++totalBlank;
              ++i;
     }

因为while(page.taglst[i] == "<br>" && i < taglen)
这个判断先执行page.taglst[i] == “
”这个判断,如果这个判断返回值为true,再执行i < taglen这个判断。
当i=taglen的时候,执行page.taglst[i] == "<br>" 这个判断就会越界


9 sizeof() 和strlen()
void Func(char str_arg[100])
{
       printf("%d\n",sizeof(str_arg));
}
int main(void)
{
    char str[]="Hello";
    printf("%d\n",sizeof(str));
    printf("%d\n",strlen(str));
    char*p=str;
    printf("%d\n",sizeof(p));
    Func(str);
}

6 5 4 4

数组作为函数参数传递的时候,退化为指针
sizeof() // 会把字符串的结束符”\0”计算进去的 // 编译时计算 与内容无关
strlen() // 进行strlen操作求字符串的长度的时候,不计算\0的。 //

10 强制转换 reinterpret_cast
char str[] = "glad to test something";
char *p = str;
p++;
int *p1 = reinterpret_cast<int *>(p);
p1++;
p = reinterpret_cast<char *>(p1); 
printf("result is %s\n", p);

结果:

result is to test something
11 析构函数调用顺序

已经有A,B,C,D4个类的定义,程序中A,B,C,D析构函数调用顺序为?

C c;
void main()
{
    A*pa=new A();
    B b;
    static D d;
    delete pa;
}

局部变量A 是通过 new 从系统的堆空间中分配的,程序运行结束之后,系统是不会自动回收分配给它的空间的,需要程序员手动调用 delete 来释放。

局部变量 B 对象的空间来自于系统的栈空间,在该方法执行结束就会由系统自动通过调用析构方法将其空间释放。

之所以是 先 A 后 B 是因为,B 是在函数执行到 结尾 “}” 的时候才调用析构函数, 而语句 delete a ; 位于函数结尾 “}” 之前。

其中全局变量和静态局部变量时从 静态存储区中划分的空间,
二者的区别在于作用域的不同,全局变量作用域大于静态局部变量(只用于声明它的函数中),
而之所以是先释放 D 在释放 C的原因是, 程序中首先调用的是 C的构造函数,然后调用的是 D 的构造函数,析构函数的调用与构造函数的调用顺序刚好相反。

C是全局对象,对它的初始化是在main函数之前,所以析构时候要放在最后。

12 类中内存分配 及 内存对齐

1

class CTest
{
    public:
        CTest():m_chData(‘\0’),m_nData(0)
        {
        }
        virtual void mem_fun(){}
    private:
        char m_chData;
        int m_nData;
        static char s_chData;
};
char CTest::s_chData=’\0’;

(1)若按4字节对齐sizeof(CTest)的值是多少?
(2)若按1字节对齐sizeof(CTest)的值是多少?

12 9

sizeof 的本质是得到某个类型的大小,确切的来说就是当创建这个类型的一个对象(或变量)的时候,需要为它分配的空间的大小。

  • 在类中,如果什么都没有,则类占用1个字节,一旦类中有其他的占用空间成员,则这1个字节就不在计算之内,如一个类只有一个int则占用4字节而不是5字节。

  • 如果只有成员函数,则还是只占用1个字节,因为类函数不占用空间

  • 虚函数因为存在一个虚函数表,指针需要4个字节,数据成员对象如果为指针则为4字节,注意有字节对齐,如果为13字节,则进位到16字节空间。

  • 当类中出现static成员变量的时候,static成员变量是存储在静态区当中的,它是一个共享的量,因此,在为这个类创建一个实例对象的时候,是无需再为static成员变量分配空间的,所以,这个类的实例对象所需要分配的空间是要排除static成员变量的,于是,当sizeof计算类的大小的时候会忽略static成员变量的大小

1 先找有没有virtual 有的话就要建立虚函数表,+4
2 static的成员变量属于类域,不算入对象中 +0
3 空类,或者只有成员函数 +1
4 对齐法则

参考:类的大小
http://blog.csdn.net/luanqibaazao/article/details/77680244
参考:内存对齐
http://blog.csdn.net/luanqibaazao/article/details/77658586


13 Java中 方法重载和方法重写

14 函数fun的功能是:求ss所指字符串数组中长度最短的字符串所在的行下标,作为函数值返回

15 基类与派生类的函数调用

父类指针指向子类实例对象,调用普通重写方法时,会调用父类中的方法。而调用被子类重写虚函数时,会调用子类中的方法。


16 回文子串

17 输出数组的全排列

18 static
static int a = 3;

静态变量值创建一次,初始化一次


19 类函数调用
#include<iostream>
using namespace std;
class MyClass
{
public:
    MyClass(int i = 0)
    {
        cout << i;
    }
    MyClass(const MyClass &x)
    {
        cout << 2;
    }
    MyClass &operator=(const MyClass &x)
    {
        cout << 3;
        return *this;
    }
    ~MyClass()
    {
        cout << 4;
    }
};
int main()
{
    MyClass obj1(1), obj2(2);
    MyClass obj3 = obj1;
    return 0;
}

运行时的输出结果是()

122444

C MyClass obj3 = obj1;
obj3还不存在,所以调用拷贝构造函数输出2,
如果obj3存在,obj3=obj,则调用复制运算符重载函数,输出3

20 函数返回指针指向栈内存

常量字符串的相关讨论

http://blog.csdn.net/luanqibaazao/article/details/77834780

//返回的是局部变量的地址,该地址位于动态数据区,栈里
char *s1()
{
    char p[] = "Hello world!";
    return p;
}

返回 Hello world!

//返回的是字符串常量的指针,指向静态数据区
char *s2()
{
    char *q = "Hello world!";
    return q;
}

返回 乱码


//返回的是静态局部变量的地址,该地址位于静态数据区
char *s3()
{
    static char r[] = "Hello world!";
    return r;
}

返回 Hello world!

另外 注意常量字符串位于静态存储区 不可修改

char p1[] = "hello world"; 
char *p2  = "hello world";

p1[2] = 'A'; // √
p2[2] = 'A'; // x  指向静态存储区 不可修改
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值