来源:http://blog.csdn.net/mishifangxiangdefeng/article/details/8120474
一、填空题(共17题,每题3分,总共51分)
1.设有int a = 5, *b, **c,执行语句c = &b, b = &a后,**c的值为________
答:5
2.以下程序是否有误,如果无误,请写出执行的次数________
- x = -1;
- do
- {
- x = x * x;
- }while(!x);
答:1
3.设有如下定义:
- struct sk
- {
- int a;
- float b;
- }data;
- int *p;
若要使p指向data中的a域,正确的赋值语句是________
答:p = &data.a;
4.用变量a给出下面的定义,一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型________
答:int (*a)[10](int)
5.若有语句:int array[2][3][4],则数组array的元素个数为________
答:24
6.已知int a[5], *p = a,则(p+1)等价于________
答:a[1]的地址
7.一个C源程序必须包含一个________函数
答:main
8.Intel X86 PC上以下程序运行的输出值是________
- int main(int argc, char *argv[])
- {
- union
- {
- struct
- {
- unsigned short s1:3;
- unsigned short s2:3;
- unsigned short s3:3;
- }x;
- char c;
- }v;
- v.c = 103;
- cout<<v.x.s1<<endl;
- return 0;
- }
- 答:7
- 103转换为8位的二进制为01100111,存储方式如下:
- 01|100|111
- __|___|___
- s3|s2 |s1
9.请用文字说明p是何种类型变量:int (*p)[n];________
答:p是指针一个二维int型数组的指针。注意,p不是函数指针数组,如果是函数指针数组,应该写成int (*p)[n]()
10.编程实现两个数互换
- int main(int argc, char *argv[])
- {
- int temp, x, y;
- cin>>x>>y;
- temp = x;
- ________
- ________
- cout<<x<<','<<y;
- }
答:x = y; y = temp;
11.32位系统中,size_SA值是________
- struct
- {
- int a1:8;
- int a2:8;
- char a3[2];
- char a4[2];
- }sA;
- int size_SA = sizeof(sA);
- 答:8
- 以最大数据类型为准进行对齐,与位域无关。本例中最大数据类型是int,对齐大小是4B。
- a1和a2共4B,a3和a4共4B。一共8B
12.以下程序输出结果m是________
- int w = 1, x = 2, y = 3, z = 4;
- m = (w < x) ? w : x;
- m = (w < y) ? w : y;
- m = (w < z) ? w : z;
- cout<<"m="<<m;
答:1
13.函数t()、f()的定义如下所示,若调用函数t时传递给x的值为3,并且调用函数f()时,第一个参数采用传值(call by value)方式,第二个参数采用传引用(call by reference)方式,则函数t的返回值为________
- int t(int x)
- {
- int a;
- a = 3 * x - 1;
- f(x, a);
- return a+x;
- }
- void f(int r, int &s)
- {
- int x;
- x = 2 * r + 1;
- s = s * r;
- r = s - x;
- return ;
- }
答:27
14.下述程序的运行结果是________
- int main(int argc, char *argv)
- {
- short unsigned int a = 5;
- int b = 7;
- int c = b + a > 0 ? a + b : a - b;
- cout<<a+b<<' '<<b+c<<' '<<c+a<<endl;
- return 0;
- }
答:-2 5 17
15.下述程序的运行结果是________
- int main(int argc, char *argv[])
- {
- int a, b, c;
- c = a = 0x30, b = 0x60;
- a = c | b >> 4;
- cout<<a<<' '<<b<<' '<<c<<endl;
- return 0;
- }
- 答:54 96 48
- 移位运算符的优先级较高,先执行移位操作,得a=0x36,即54
16.下面程序的运行结果是________
- char *p = "abcdefgh";
- p += 3;
- cout<<strlen(strcpy(p, "ABCD"))<<endl;
- 答:运行出错
- 因为p的对象存储于文字常量区,不能对其进行修改
17.下述程序输出结果是________
- #define CAL(x, y) (x * x - y * y)
- int main(int argc, char *argv[])
- {
- int a = CAL(4, 3);
- int b = CAL(3, 2);
- cout<<a<<' '<<b<<' '<<CAL(a+1, b-1)<<endl;
- return 0;
- }
答:7 5 4
二、编程题(第1题10分,第2题15分,总共25分)
三、专业题(简答题)(嵌入式、windows和算法三个方向请根据申请岗位选择一个方向答题)(每小题8分)
嵌入式平台方向
- (1)多线程的优点:
- 无需跨进程边界;
- 程序逻辑和控制方式简单;
- 所有线程可以直接共享内存和变量等;
- 线程方式消耗的总资源比进程方式好;
- (2)多线程缺点:
- 每个线程与主程序共用地址空间,受限于2GB地址空间;
- 线程之间的同步和加锁控制比较麻烦;
- 一个线程的崩溃可能影响到整个程序的稳定性;
- 到达一定的线程数程度后,即使再增加CPU也无法提高性能;
- 线程能够提高的总性能有限,而且线程多了之后,线程本身的调度也是一个麻烦事儿,需要消耗较多的CPU
- (3)多进程优点:
- 每个进程互相独立,不影响主程序的稳定性,子进程崩溃没关系;
- 可以尽量减少线程加锁/解锁的影响,极大提高性能,就算是线程运行的模块算法效率低也没关系;
- 通过增加CPU,就可以容易扩充性能;
- 每个子进程都有2GB地址空间和相关资源,总体能够达到的性能上限非常大
- (4)多进程缺点:
- 逻辑控制复杂,需要和主程序交互;
- 多进程调度开销比较大;
- 需要跨进程边界,如果有大数据量传送,就不太好,适合小数据量传送、密集运算
- 1.套接字(socket)
- 2.共享内存(share memory)
- 共享内存实现分为两个步骤:
- (1)创建共享内存,使用shmget函数。
- (2)映射共享内存,将这段创建的共享内存映射到具体的进程空间去,使用shmat函数。
- 3.信号(signal)
- (1)信号类型,下面是几种常见的信号:
- SIGHUP:从终端上发出的结束信号
- SIGINT:来自键盘的中断信号(Ctrl-C)
- SIGKILL:该信号结束接收信号的进程
- SIGTERM:kill命令发生的信号
- SIGCHLD:标识了进程停止或结束的信号
- SIGSTOP:来自键盘(Ctrl-Z)或调试程序的停止执行信号
- (2)信号处理:
- 1.忽略此信号
- 2.执行用户希望的动作
- 3.执行系统默认动作
- (3)信号发送:
- 发送信号的主要函数有kill和raise。kill既可以向自身发送信号,也可以向其他进程发送信号。与kill函数不同的是,raise函数是向进程自身发送信号。
- 4.消息队列(message queue)
- (1)定义:unix早期通信机制之一的信号能够传送的信息量有限,管道则只能传送无格式的字节流,这无疑会给应用程序开发带来不便。消息队列(也叫做报文队列)则克服了这些缺点。
- (2)发展:消息队列就是一个消息的链表。可以把消息看作一个记录,具有特定的格式。进程可以向中按照一定的规则添加新消息;另一些进程则可以从消息队列中读走消息。
- (3)持续性:系统V消息队列是随内核持续的,只有在内核重起或者人工删除时,该消息队列才会被删除。
- (4)键值:消息队列的内核持续性要求每个消息队列都在系统范围内对应唯一的键值,所以,要获得一个消息队列的描述字,必须提供该消息队列的键值。
- 5.管道(pipe)和有名管道(FIFO);
- 当一个管道建立时,它会创建两个文件描述符:filedis[0]用于读管道,filedis[1]用于写管道。
- 管道关闭:关闭管道只需将这两个文件描述符关闭即可,可以使用普通的close函数逐个关闭。
- 命名管道和无名管道基本相模同,但也有不同点:无名管道只能由父子进程使用;但是通过命名管道,不相关的进程也能交换数据。
- Bootloader(引 导加载程序)是系统加点后运行的第一段代码。在嵌入式系统中,通常并没有香BIOS那样的固件程序(有的嵌入式CPU会在芯片内部嵌入一段短小的程序,一 般用来将Bootloader装载进AM中,因此 Bootloader的作用于PC机上的BIOS类似),通过Booloader可以完成对系统板上的 主要部件如CPU,SDRAM,FLASH和串口等进行初始化,也可以下载文件到系统板,对FLASH进行擦出于编程。在一个基于ARM的嵌入式系统中, 系统的在上电或复位时通常都从地址 0x00000000处开始执行,而这个地址安排的通常就是系统Bootloader。通过这段小程序可以初始化硬件 设备,建立内存空间的映射。从而将系统的软硬件环境带到一个合适的状态,一边最终调用操作系统内核准备好正确的环境。
- Bootloader一般包含一下几个必备功能
- (1)初始化处理器。这个动作都是用汇编语言完成的,当电源接通就会执行这个动作,通常只有两三个汇编指令,目的是将CPU的控制权转交给硬件初始化的程序。
- (2)初始化一些必要的硬件,这个动作都是汇编语言完成的。主要是初始化CPU,SDRAM等,其他硬件,例如串口,可以由C语言等比较高级的语言来完成后续动作。
- (3)设置处理器的寄存器以及内存,关掉所有输入管脚(包括终端管脚),以防突然有信号进入妨碍我们接下来的硬件初始化动作。然后初始化串口,以便后续运行的程序能够同Host端进行通信,便于调试。
- (4) 从特定的位置把操作系统和文件系统调入内存,并设置一些必要的初始参数。然后把CPU的控制权交给操作系统。有的Bootloader会先从串讲偶或者网 络其他路径得到内核的映象文件。然后把这些文件写入到target系统的Flash或者其他的存储介质,然后把内核载入到RAM执行,同时交出控制 权。