C++小题(五)

/*
开发C代码时,经常见到如下类型的结构体定义:
typedef struct list_t{
	struct list_t *next;
	struct list_t *prev;
	char data[0];
}list_t;
最后一行char data[0];的作用是?
正确答案: A B   

A方便管理内存缓冲区
B减少内存碎片化
C标识结构体结束
D没有作用


柔性数组,它只能放在结构体末尾,是
申明一个长度为0的数组,就可以使得这个结构体是可变长的。对于编译器来说,此时长度为0的数组并不占用空间,
因为数组名本身不占空间,它只是一个偏移量, 数组名这个符号本身代 表了一个不可修改的地址常量 (注意:数组名永远都不会是指针! ),
但对于这个数组的大小,我们可以进行动态分配 请仔细理解后半部分,对于编译器而言,数组名仅仅是一个符号,它不会占用任何空间,
它在结构体中,只是代表了一个偏移量,代表一个不可修改的地址常量!
 对于0长数组的这个特点,很容易构造出变成结构体,如缓冲区,数据包等等:
注意:构造缓冲区就是方便管理内存缓冲区,减少内存碎片化,它的作用不是标志结构体结束,而是扩展
柔性数组是C99的扩展,简而言之就是一个在struct结构里的标识占位符(不占结构struct的空间)。
*/
//
/*
int main( ){ 
     int i; 
     for(i = 0; i<5;i++){ 
        int pid = fork(); 
        if(pid == 0){ 
            //do something 
        } else { 
        	//do something 
        } 
    }
    // do somthing,sleep
    return 0;
}
请问下面的程序最后会产生多少个进程? 32
i=0时,共有两个进程: 主进程和主进程创建的第一个进程
i=1时,以上两个进程分别创建新的进程,此时共有四个进程
i=2时,以上四个进程分别创建新的进程,此时共有8个进程
....
依次类推, 当i=n时,共创建2^(n+1)个进程

每一个fork()出来的新进程,和父进程使用相同的代码段,复制父进程的数据段和堆栈段,不过有“逻辑”复制和“物理”复制之分,
在本题没有影响。也就是说每一个fork()出的新进程和父进程有相同大小的i,并且执行位置也是一样的
*/
/
/*
下面关于"指针"的描述不正确的是()
正确答案: A   

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

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

/*
下面有关空指针和未初始化指针,说法错误的是?
正确答案: D   

A 对0x0这个地址取值是非法的
B 空指针可以确保不指向任何对象或函数; 而未初始化指针则可能指向任何地方。
C 空指针与任何对象或函数的指针值都不相等
D mallc在其内存分配失败时返回的是一个未初始化的指针

空指针与野指针的区别,空指针也就是通常指向为NULL的指针,

野指针就是指向一块未知的内存区域(可以是通过malloc或new申请空间后,释放后没有将指针置为空),
也有可能定义了一个指针没有初始化,由于内存空间中的值在未赋值之前是随机数,所以也有可能诞生野指针。

就上面这道题目而言:
A肯定是对的,无法为内存为0的地址取地址
B也是对的
C空指针的值肯定是NULL,也就是0,而其他指针都有对象了,有对象就有地址,有地址也就有值了,所以两个值是不可能相等的
D malloc申请内存空间失败的时候,返回的值为NULL,而不是任意的。
*/
///
/*
有如下程序段:
int i, n = 0;
float x = 1, y1 = 2.1 / 1.9, y2 = 1.9 / 2.1;
for ( i = 1; i < 22; i++ )
 x = x * y1;
while ( x != 1.0 )
{
 x = x * y2; n++;
}
printf( “ %d / n ”, n );
请问执行结果是:无限循环
浮点数的比较不可以用 == 或者 != 
*/
//
/*
下列关于构造函数的描述中,错误的是( )
正确答案: D   

A构造函数可以设置默认的参数
B构造函数在定义类对象的自动执行
C构造函数可以是内联函数
D构造函数不可以重载
*/

/*
执行下面语句后的输出为

int I=1;
if(I<=0)
    printf("****\n") ;
else
    printf("%%%%\n");
正确答案: A   

A %%
B ****
C 有语法错,不能正确执行
D %%%%
在printf中的%作为转义符,两个%才相当于1个%
*/
//
/*
C++将父类的析构函数定义为虚函数,下列正确的是哪个?
正确答案: A   

A释放父类指针时能正确释放子类对象
B释放子类指针时能正确释放父类对象
C这样做是错误的
D以上全错

C++的多态肯定是使用父类的指针指向子类的对象,所以肯定是释放子类的对象,
如果不使用虚函数的话, 父类的指针就只能够释放父类的对象。
*/
/
/*
STL中的一级容器有:
正确答案: D   

A vector, deque, list, set, multiset, map, multimap.
B 序列容器,关联容器,容器适配器
C set, multiset, map, multimap.
D vector, deque, list.

STL中的常用容器包括:顺序性容器(vector、deque、list)、关联容器(map、set)、容器适配器(queue、stack)。
STL中一级容器是指, 容器元素本身是基本类型, 非组合类型。
set, multiset中元素类型是pair<key_type, key_type>;
map, multimap中元素类型是pair<key_type, value_type>;
*/

/*
void test(void *data) {
    unsigned int value = (此处应填入)
    printf("%u", value);
}
using namespace std;
int main() {
    unsigned int value = 10;
    test(&value);
    return 0;
}
正确答案: D   

A *data
B (unsigned int)(*data)
C (unsigned*)data
D *((unsigned int *)data)

参数是 void*, 编译器不知道它的具体数值类型,不能直接取值,B错
先转换为具体指针类型,然后再取值
*/
///
/*
class A 
{ 
    public: 
    ~A(); 
}; 
A::~A() 
{ 
    printf("delete A "); 
}
class B : public A 
{ 
    public: 
    ~B(); 
}; 
B::~B() 
{ 
    printf("delete B "); 
} 
请问执行以下代码
A *pa = new B();
delete pa; 
输出的串是()
正确答案: A  
A delete A
B delete B
C delete B delete A
D delete A delete B
析构函数做最后的“清场工作”,
一般当派生类对象从内存中撤销时,先调用派生类的析构函数,再调用基类析构函数;
但,若用new建立了临时对象,在用delete撤销对象是,系统会只执行基类的析构函数,而不执行派生类的析构函数。
如果将基类的析构函数声明为虚函数,由基类所有派生类的析构函数自动成为虚函数(即使析构函数名不同)。
将析构函数加上vitual,实现具体对象的 动态关联 ,在运行阶段,先调用派生类析构,在调用基类析构
*/
/
/*
写出下列程序的运行结果。

#include "stdio.h"
int sum(int a)
{
    auto int c = 0;
    static int b = 3;
    c += 1;
    b += 2;
    return (a + b + c);
}
int main()
{
    int i;
    int a = 2;
    for (i = 0; i < 5; i++) 
    { 
        printf("%d,", sum(a)); 
    } 
} 
正确答案: B   
A 6,8,10,12,14,
B 8,10,12,14,16,
C 10,12,14,16,18
D 12,14,16,18,20
auto int 表示的是局部变量,在我们声明局部变量,或者函数参数,可以加上这个关键字,表明是分配在堆栈中
本程序中的变量b声明为static静态全局变量,所以它的作用域是全局作用域,每次调用sum函数都会累加2
所以答案是8,10,12,14,16
*/
/
/*
下面是折半查找的实现,data是按升序排列的数据,x是查找下标,y是查找的上标,
v是查找的数值,返回v在data的索引,若没找到返回-1。代码不正确是__5__。

public int bsearch(int[] data, int x, int y, int v) {
    int m;
    while(x<y){ //1
        m = x + (y-x)/2; //2
        if(data[m] == v) return m; //3
        else if(data[m] > v) y = m; //4
        else x = m; //5
    }
    return -1; //6
}
上下标没有写清楚,题目所指的应该是[x,y),这样5应该是m-1
而在下标为[x,y]的情况下,1,4,5都是有问题的。。。。正确版本应该是这样吧
while(x<=y) {
        m = x + (y-x)/2; //2
        if(data[m] == v) return m; //3
        else if(data[m] > v) y = m-1; //4
        else x = m+1; //5
    }

补充:这里下标是个坑,记住上限有没有包含就可以对付1,4,5处的问题(熟记理解两个版本的代码区别),
然后是2,写成x+(y-x)/2是防止xy都很大的情况下x+y越界。这样的话应对二分查找应该够了
*/
/
/*
下面有关static类变量和实例变量的描述,正确的有?
正确答案: A B C D   

A static类变量又叫静态成员变量,它不需要创建对象就可以已经在内存中存在了
B 在创建实例对象的时候,内存中会为每一个实例对象的每一个非静态成员变量开辟一段内存空间,用来存储这个对象所有的非静态成员变量值
C static类变量是所有对象共有,其中一个对象将它值改变,其他对象得到的就是改变后的结果
D 实例变量则属对象私有,某一个对象将其值改变,不影响其他对象

类变量也叫静态变量,也就是在变量前加了static 的变量;
实例变量也叫对象变量,即没加static 的变量;
A:static变量在未初始化时存储在BSS段,初始化后存储在data section数据段,A正确
B:非静态成员则不会开辟空间,B正确
C:static变量是类变量,可理解为只有一份,C正确
D:可理解为:对实例对象,每个实例均有各自的一份变量,改变其值只是改变了自己的那一份,D正确
*/
/
/*
下面哪些方式可以用于线程之间的同步?
正确答案: A B C D  

A临界区
B互斥区
C事件
D信号量
(1) 进程间通信方法有:文件映射、共享内存、匿名管道、命名管道、邮件槽、剪切板、动态数据交换、对象连接与嵌入、动态连接库、远程过程调用等
(2) 事件、临界区、互斥量、信号量可以实现线程同步
*/ 
/
/*
如下函数,在32bits系统foo(2^31-3)的值是___1____(这里的^是指数的意思)
int foo (int x)
   return x & -x;
*/
/
/*
下面对静态成员的描述中,正确的是:
正确答案: D   你的答案: D (正确)

A静态数据成员可以在类体内初始化
B静态数据成员不可以被类的对象调用
C静态数据成员不能受private控制符的作用
D静态数据成员可以直接用类名调用

静态数据成员不属于某一个对象,所以要在类外初始化,A错;
它是所以对象的公共成员,需要类名调用,B错;
静态数据成员初始化与这些权限控制的没有关系,C错;
故答案为D
*/

/
/*
下列关于 clone 和 fork 的区别描述正确的有?
正确答案: C   
A clone和fork最大不同在于fork不再复制父进程的栈空间,而是自己创建一个新的。
B clone和fork最大不同在于clone不再复制父进程的栈空间,而是自己创建一个新的。
C clone是fork的升级版本,不仅可以创建进程或者线程,还可以指定创建新的命名空间(namespace)、有选择的继承父进程的内存、甚至可以将创建出来的进程变成父进程的兄弟进程等等
D fork是clone的升级版本,不仅可以创建进程或者线程,还可以指定创建新的命名空间(namespace)、有选择的继承父进程的内存、甚至可以将创建出来的进程变成父进程的兄弟进程等等
*/
///
/*
以下代码的输出结果是?
char *p="abc";
char *q="abc123";
while(*p=*q)
print("%c %c",*p,*q);
正确答案: D   你的答案: D (正确)

A aabbcc
B aabbcc123
C abcabc123
D 代码段错误

字符串常量赋值会出错*/

/*
下面程序段包含4个函数,其中具有隐含this指针的是()
int f1();
class T
{
    public:static int f2();
    private:friend int f3();
    protect:int f4();
};
正确答案: D   你的答案: D (正确)

A f1
B f2
C f3
D f4

静态成员函数属于整个类所拥有,没有this指针
友员函数不是这个类的成员,没有
类的非静态成员函数  有
*/

/*
boolalpha,函数名称,功能是把bool值显示为true或false。
*/

/*
如下程序

void main()
{
    float a = 1;
    cout << boolalpha << ((int)a == (int &)a);
    float b = 0;
    cout << boolalpha << ((int)b == (int &)b);
}

该程序输出结果为
正确答案: D   

truetrue
falsefalse
truefalse
falsetrue
(int&)a:将a的引用强制转换为整型,意思是a所在的内存,本来定义的时候为float类型并初始为1.0f,但现在我要按int类型解释这段内存
(也就是说a所在的内存地址中的数据本来是按float型存储表示的,你非要按int型来解释不可)。
1.0f   在内存中的存储为
0   011   1111   1   000   0000   0000   0000   0000   0000.
把他按整型数解释为2^29+2^28+2^27+2^26+2^25+2^24+2^23=1065353216
(int&)a 相当于*(int*)&a ,*(int*)(&a),*((int*)&a)  
(int)a   a在内存中的值转换成int类型 
*/

/*
有如下模板定义:
template <class T>
T fun(T x,T y){
    return x*x+y*y;
}
在下列对fun的调用中,错误的是()
正确答案: B   你的答案: B (正确)

fun(1, 2)
fun(1.0, 2)
fun(2.0, 1.0)
fun<float>(1, 2.0)
这里T要求类型一致
A,类型一致,为int型
B,类型不一致,错
C,类型一致,为folat型
D,用<float>进行声明,后面的实参会强制类型转换为float,所以也是类型一致的。
*/

/*
以下不能正确定义二维数组的选项是______。
正确答案: D   

int a[2][2]={{1},{2}};
int a[][2]={1,2,3,4};
int a[2][2]={{1},2,3};
int a[2][]={{1,2},{3,4}};

对于二维数组,行数可以省略,但列数一定要指定,因为编译器根据列数来进行寻址
*/
/
/*
关于“深拷贝”,下列说法正确的是:
正确答案: A   

A 会拷贝动态分配的成员对象
B 会拷贝成员数据的值
C 会拷贝静态分配的成员对象
D B和C都对

静态成员的数据只有一份为大家共享,所以不能深拷贝
深拷贝是指源对象与拷贝对象互相独立,其中任何一个对象的改动都不会对另外一个对象造成影响。
浅拷贝是指源对象与拷贝对象共用一份实体,仅仅是引用的变量不同(名称不同)。对其中任何一个对象的改动都会影响另外一个对象
*/
//
/*
下面程序的功能是输出数组的全排列。请填空
void perm(int list[], int k, int m)
{
    if (    )
    {
        copy(list,list+m,ostream_iterator<int>(cout," "));
        cout<<endl;
        return;
    }
    for (int i=k; i<=m; i++)
    {
        swap(&list[k],&list[i]);
        (    );
        swap(&list[k],&list[i]);
    }
}
for循环的作用是为先把index值为k的元素后面的元素依次与index为k的元素交换,相当于得到index为k的元素可能的取值情况,
然后使用递归得到index为k+1的元素位置可能的所有取值。
然而对index为k的位置元素进行取值的时候,操作过后需要还原避免取下一个值的时候错误,因此就有了第二个swap操作。
由上分析可知,第一个空格应该为k==m,当index值到了m的时候输出即可,因为index为m后面已经没有元素与其进行对调.
*/
/
/*
阅读下列函数说明和C代码,将应填进(n)处的字句写在答题纸的对应栏内。
【说明】设有一个带表头结点的双向循环链表L,每个结点有4个数据成员:指向先驱结点的指针prior、指向后继结点的指针next、存放数据的成员data和访问频度freq。所有结点的freq初始时都为0.每当在链表上进行一次L.Locate(x)操纵时,令元素值x的结点的访问频度freq加1,并将该结点前移,链接到现它的访问频度相等的结点后面,使得链表中所有结点保持按访问频度递减的顺序排列,以使频繁访问的结点总是靠近表头。
【函数】
void Locate(int &x)
{
< 结点类型说明 >
	*p = first->next;
	while (p != first &&   1 ) p = p->next;
	if (p != first)
	{
		2 ;
		< 结点类型说明 >
	*current = p;
	current->prior->next = current->next;
	current->next->prior = current->prior;
	p = current->prior;
	while (p != first && 3 ) p = p->prior;
	current->next = 4 ;
	current->prior = p;
	p->next->prior = current;
	p->next = 5 ;
}
else
	printf(“Sorry. Not find!\n”);  \*没找到*\
}

你的答案 (正确)

1 p->data!=x

2 p->freq++

3 current->freq>p->freq

4 p->next

5 current
*/ 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
电子协会C级考试是一项涵盖电子工程相关知识的考试。该考试旨在评估考生对电子工程原理、电子元器件、电路设计、电子产品测试等方面的了解程度和应用能力。 在考试前,考生应充分准备,掌握电子工程基础知识。首先,了解电子元器件的种类、功能和特性,比如二极管、晶体管、集成电路等。其次,掌握电路设计的基本原理,包括电路图的绘制、电流电压的计算、电路参数的选择等。此外,还需了解电子产品测试的方法和步骤,包括使用示波器、信号发生器等仪器进行测量和分析。 在考试过程中,要注意答题的准确性和清晰性。对于选择题而言,要仔细阅读题目,在选项之间进行比较,选择最合适的答案。对于计算题,要注意单位的转换和计算过程的严谨性。在解答题时,要明确问题,清晰地陈述观点,并给出充分的理由和论据。 考试结束后,要及时进行回顾和总结。审查自己可能存在的错误和不足之处,以便在以后的学习和备考中改进和提升。同时,也要查阅相关资料和参考书籍,扩大和深化知识面,为以后的学习和职业发展打下坚实的基础。 总之,电子协会C级考试是一项对电子工程知识和应用能力的综合评估。考生需要充分准备、细心答题,并在考后不断总结和提升。这样才能取得好的成绩,并在电子工程领域有更好的发展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值