您的位置:首页 > 编程语言 > C语言/C++

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

2017-09-02 21:12 211 查看
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  指向静态存储区 不可修改
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: