【重要】CC++嵌⼊式,必会的理论概念#define MIN(A,B) ((A) <= (B) (A):(B))
#error 命令,将停⽌编译并输出⽤户⾃定义的错误消息。
for(;;) ⽆条件循环,效率更⾼,反汇编查看的话没有判断只有跳转。
int p; //整形变量p
int *p; //⼀个指向整形数的指针p
int **p; //⼀个指向整形数的地址的⼆级指针p
int *p[3]; //⼀个包含有3个元素的指针数组p
int (*p)[3]; //⼀个指向具有3个整型元素的⼀维数组的指针p
int *func(int, int); //⼀个返回整形数地址的函数func,含2整形参
int (*func)(int, int); //⼀个指向函数地址的函数指针func,含2整形参
int (*func[10])(int); // ⼀个有10个函数指针的数组,每个指针指向⼀个函数,该函数有⼀个整型参数并返回⼀个整型数
volatile
并⾏设备的硬件寄存器;
中断服务⼦程序访问的⾮⾃动变量;
多线程中共享的变量;
#define BIT3 (0×1<<3)
static int a;
void set_bit3(void)
{
a |= BIT3;
}
void clear_bit3(void)
{
a &= ~BIT3;
}
int *ptr;
ptr = (int *)0x67a9;
*ptr = 0xaa55;
1). ISR 不能返回⼀个值。
2). ISR 不能传递参数。
3). 在许多的处理器/编译器中,浮点⼀般都是不可重⼊的。ISR应该是短⽽有效率的,在ISR中做浮点运算是不明智的。
4).printf()经常有重⼊和性能上的问题。
对于⼀个int型不是16位的处理器为说,应编写如下:
unsigned int compzero = ~0;
char *ptr;
if ((ptr = (char *)malloc(0)) == NULL)
puts(“Got a null pointer”);
else
puts(“Got a valid pointer”); // 输出(malloc分配成功了,返回合法的指针)
sizeof如⽤于数组,只能测出静态数组的⼤⼩,⽆法检测动态分配的或外部数组⼤⼩。
getmemory函数中的malloc 不能返回动态内存, free()对str操作很危险
char szstr[10];
strcpy(szstr,”0123456789″);
长度不⼀样,会造成⾮法的操作。(后⾯的字符串常量是11个字符,包含\0)
纯虚函数如何定义?使⽤时应注意什么?
virtual void f()=0;
是接⼝,⼦类必须要实现
进程死锁的原因:资源竞争及进程推进顺序⾮法
死锁的4个必要条件:互斥、请求保持、不可剥夺、环路
死锁的处理:鸵鸟策略、预防策略、避免策略、检测与解除死锁
操作系统中进程调度策略有哪⼏种?FCFS(先来先服务),优先级,时间⽚轮转,多级反馈
TCP 服务提供了数据流传输、可靠性、有效流控制、全双⼯操作和多路复⽤技术等。
UDP 并不提供对 IP 协议的可靠机制、流控制以及错误恢复功能等。由于 UDP ⽐较简单, UDP头包含很少的字节,⽐ TCP 负载消耗少。tcp: 提供稳定的传输服务,有流量控制,缺点是包头⼤,冗余性不好
molloc函数udp: 不提供稳定的服务,包头⼩,开销⼩
让程序跳转到绝对地址是0x100000去执⾏:
函数指针:void (*) ();
定义类型:typedef void(*)() voidFuncPtr;
类型强转:*((voidFuncPtr)0x100000) ();
unsigned short A = 10;
printf("~A = %u\n", ~A); //4294967285
char c=128;
printf("c=%d\n",c);//-128
对于⼀个频繁使⽤的短⼩函数,在C语⾔中应⽤什么实现,在C++中应⽤什么实现?
答案:c⽤宏定义,c++⽤inline
软件测试都有那些种类?
答案:⿊盒:针对系统功能的测试 ⽩合:测试函数功能,各函数接⼝
预编译:
1、总是使⽤不经常改动的⼤型代码体。
2、多个模块都使⽤⼀组头⽂件或宏定义。
malloc和new区别:
1. malloc是C的函数,new是C++中的操作符;
2.malloc函数只分配内存,new不仅分配了内存还调⽤构造函数对对象进⾏了初始化操作;
3.malloc分配内存后返回内存地址为⽆类型指针,new出来的指针时带类型信息的。
【C 语⾔】
1、 C 和 C++有什么不同?
1)C语⾔⾯向过程编程,重程序的实现;C++⾯向对象编程,重程序的设计;
2)C是C++的⼀个⼦集;C++全⾯兼容C;
3)C++相对于C引⼊了重载、内联函数、异常处理、类的封装/继承/多态、以及/容器类等…
2、进程和线程的异同、关系?
1)进程:是系统资源分配和调度的基本单位,有⾃⼰的pid;
线程:是运⾏的基本单位,有⾃⼰的tid。
2)进程:⼀个进程⾄少拥有1个线程,为主线程;
线程:同⼀个进程中的线程可以并发,且共享进程的资源,拥有⾃⼰独⽴的栈空间和执⾏序列。
3)进程有独⽴的地址空间,多进程程序要⽐多线程程序健壮,但进程切换时,需要复制PCB,资源开销⼤,效率稍低; 线程没有独⽴地址空间,必须依赖具体的进程才能执⾏,线程的切换不需要复制PCB资源开销⼩,效率⽐进程⾼;
4)进程能实现跨机器迁移;
线程适合于SMP(对称多处理器)机器上运⾏。
3、进程间通信都有哪⼏种机制?其中最快的机制为哪种?
1)管道(pipe):
管道⽤于具有亲缘关系的进程间通信,其中有名管道可实现⽆亲缘关系的进程间通信;
2)信号(signal):
软中断机制,进程收到信号相当于处理器收到中断请求,⽤于通知进程对应的事件处理;
IPC通信>>
3)消息队列(message queue)
克服了管道和信号中量有限的缺点,利⽤内存中公共消息缓冲区实现进程间通信;
4)共享内存(shared memory)——【最快的IPC通信形式】因为进程可以直接读写内存,不需要数据的拷贝。
内核维护⼀块由多个进程均可访问的内存,实现进程通信,需要互斥锁或信号量集配合实现同步;
5)信号量集(semaphore)
多进程之间或同⼀进程内的多线程之间实现同步和互斥的⼿段;
socket⽹络通信>>
6)套接字(socket):
实现⽹络中不同机器之间的进程间通信,应⽤⼴泛。
4、请简述 socket 编程中 client 和 server 的⼤致步骤?
以基于TCP的编程模型为例。
server:
1) 创建通讯端(套接字) - socket
2) 初始化服务器的地址空间 - sockaddr_in成员
3) 将套接字和服务器地址空间绑定 - bind
4) 监听通讯端- listen
5) 等待客户端连接的到来,到来返回连接描述符 - accept
6) 通过连接描述符进⾏读取客户端数据 - read //data
7) 通过连接描述符给客户端响应 - write
8) 关闭连接描述符 – close
client:
1) 创建通讯端(套接字) - socket
2) 初始化服务器的地址空间(ip转换) - sockaddr_in成员/inet_pton
3) 连接服务器,成功返回即连接成功 - connect
4) 向服务器发送请求信息 - write
5) 从服务器获取响应信息 - read
6) 对响应信息做相关的数据处理 - //data
7) 关闭通讯端(套接字) – close
5、进程之间通信的途径?进程死锁的原因?死锁的 4 个必要条件?
进程通信途径:
死锁:多个进程循环等待它⽅占有的资源⽽⽆限期地僵持下去的⼀种程序运⾏情况。
进程死锁原因:
1)系统提供资源有限;
2)系统资源分配不当;
3)多进程中进程运⾏推进顺序不合理;
解除死锁条件:
1)互斥条件:1个资源每次只能被1个进程使⽤。
2)请求与保持条件:1个进程因请求资源阻塞时,对已获得的资源保持不放。
3)不抢占条件:进程已获得的资源在未使⽤完之前,不能强⾏抢占。
4)循环等待条件:多进程之间形成⼀种头尾相接的循环等待资源关系。
6、死锁的处理?操作系统中进程调度策略有哪⼏种?
死锁的处理⽅法:
1)最简单最常⽤的是:系统重新启动。但代价⼤,进程已完成的运算都付之东流。
2)撤销进程,剥夺资源。⼀次性终⽌参与死锁的进程,或者逆序逐步撤销参与死锁的进程,需考虑优先级及代价。
进程调度的策略:
1)先来先服务(FCFS)
2)优先级
3)时间⽚轮转
4)分级调度
5)多级反馈轮转
【区别于】常⽤的作业调度算法有:先来先服务算法(FCFS)、最短作业优先算法(SJF)、最⾼响应⽐优先算法(HRRN)、优先级调度算法、均衡调度算法等。
7、 TCP 和 UDP 的区别?简述 3 次握⼿协议?
TCP和UDP的区别:
1)TCP⾯向连接;UDP⾯向⽆连接;
2)TCP传输⽆差错不丢失,安全可靠,效率不如UDP;UDP传输容易丢包,安全性较差,传输效率⾼于TCP;
3)TCP连接点对点;UDP⽀持多对多交互通信;
4)TCP⾸部开销20字节;UDP⾸部开销8字节;
5)TCP是全双⼯可靠信道;UDP是不可靠信道。
【第⼀次握⼿】:建⽴连接时,客户端发送syn包(syn=j)到服务器,并进⼊SYN_SEND状态,等待服
务器确认;
SYN:同步序列编号(Synchronize Sequence Numbers)
【第⼆次握⼿】:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时⾃⼰也发送⼀个SYN包(syn=k),即SYN+ACK包,此时服务器进⼊SYN_RECV状态;
【第三次握⼿】:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进⼊ESTABLISHED状态,完成三次握⼿。
完成三次握⼿,客户端与服务器开始传送数据。
8、什么是字节对齐,为什么要对齐?怎么样实现字节对齐?
字节对齐概念:
各种类型数据按照⼀定的规则在空间上排列,⽽不是顺序的⼀个接⼀个的排放。
字节对齐原因:
1)减少CPU访存次数,提⾼CPU的访问效率;
2)提⾼对于不同硬件平台下代码的可移植性;
3)合理利⽤可以有效节省存储空间。
字节对齐⽅法:
C编译器默认为每个变量或数据单元按其⾃然对界条件分配空间。也可以通过以下2中⽅式改变对齐⽅式:
1)#pragma pack
· 使⽤伪指令#pragma pack (n),C编译器将按照n个字节对齐。
· 使⽤伪指令#pragma pack ( ),取消⾃定义字节对齐⽅式。
2)__attribute( )
· __attribute((aligned (n))),让所作⽤的结构成员对齐在n字节⾃然边界上。如果结构中有成员的长度⼤于n,则按照最⼤成员的长度来对齐。
· __attribute__ ((packed)),取消结构在编译过程中的优化对齐,按照实际占⽤字节数进⾏对齐。
9、多线程编程中要注意什么问题 ?
1)明确使⽤线程的⽬的。是对不同的资源(例如SOCKET连接)进⾏管理,考虑多个线程;
2)控制线程的调度和阻塞。如利⽤事件的触发来控制线程的调度和阻塞,也有⽤消息来控制的;
3)不能出现死锁问题。线程中如果⽤到公共资源,要考虑公共资源的线程安全。⼀般⽤互斥锁机制来控制。
4)合理使⽤sleep。何时Sleep,Sleep的⼤⼩要根据具体项⽬,做出合理安排。⼀般原则⾮阻塞状态下每个循环都要有SLeep,这样保证减少线程对CPU的抢夺。
5)线程的终⽌。⼀般要使线程体在完成⼀件⼯作的情况下终⽌,⼀般不要直接使⽤抛出线程异常的⽅式终⽌线程。
6)线程的优先级。⼀定根据程序的需要要有整体的规划。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论