不管是显示的类型转换还是隐式的类型转换,都有一个到转换结果类型的临时变量的产生:
譬如:
int i = 1.2; //实际的赋值过程可能是 int temp = 1.2; int i = temp;
无符号变量和有符号变量之间的转换是其对应的内存地址二进制表示不变。
hook机制发送消息
如果你设置的超时时间大于75秒就没有必要这样做了,因为内核中对connect有超时限制就是75秒
发送超时,接收超时,以及select超时(注: select函数并不是只用于套接口的,但是套接口编程中用的比较多)
40.int id[sizeof(unsigned long)];
这个对吗?为什么??
对
这个 sizeof是编译时运算符,编译时就确定了
可以看成和机器有关的常量。
--------------------------------------数据结构------------------------
算法的特点: 有穷性,确定性,可行性,输入,输出
算法设计要求:正确性,可读性,健壮性,效率与低存储量需求
算法的目的:时间和空间效率 (空间没问题时,追求时间效率)
静态存储:
#define LISTSIZE 100 //存储空间最大容量,依需要而定
typedef struct {
ElemType elem[LISTSIZE] ; //用于存储各个表元素
int length; //当前长度
}SqList;
动态分配:
#define LIST_INIT_SIZE 100 //线性表存储空间的初始分配量
#define LISTINCREMENT 10 //线性表存储空间的分配增量
typedef struct {
ElemType * elem ; //存储空间基址
int length; //当前长度
int listsize; //当前分配的存储容量(以sizeof(ElemType)为单位)
}SqList;
线性表顺序存储结构的优缺点
1、优点
(1)结构简单
(2)可直接定位到表中任意元素,并可随机存取元素,连续存取速度快。
2、缺点
(1)存储空间难于准确静态分配,分配大了浪费空间,分配小了又可能不够用。
(2)插入、删除操作不大方便,需要移动大量数据元素,效率较低。
线性表的链式存储结构的优缺点
1、优点
(1)存储空间动态分配,可以按需要使用。
(2)插入、删除结点操作通常只需要修改指针,不必移动数据元素。
2、缺点
(1)每一个结点附加指针域(存储密度小于1),空间利用率低。
(2)非随机存储结构,查找定位操作需从头指针处顺着链表扫描。
栈(Stack) 是限定仅在表尾进行插入或删除操作的线性表。因此,对栈来说,表尾端有其特殊含义,称为栈顶(top),相应地,表头端称为栈底(bottom)。不含元素的空表称为空栈。
//栈的顺序存储表示
#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10;
typedef struct {
SElemType * base;
SElemType * top;
int stacksize;
}SqStack;
Status GetTop (SqStack S,SElemType &e){
//若栈不空,则用e返回s的栈顶元素,并返回OK;
//否则返回ERROR
if(S.top = = S.base)
return ERROR;
e=*(S.top-1);
return OK;
} //GetTop
Status Push (SqStack &S,SElemType e){
//插入元素e为新的栈顶元素
if(S.top — S.base>=S.stacksize){
//---栈满,追加存储空间---
S.base = (SElemType *)realloc(S.base,(S.stacksize+STACKINCREMENT) *sizeof(SElemType))
if(!S.base)exit(0VERFLOW);//存储分配失败
S.top=S.base+S.stacksize;
S.stacksize+ = STACKINCREMENT;
}
*S.top++ = e;
return OK;
}//Push
Status Pop( Sqstack &S , SElemType &e)
//若栈不空,则删除s的栈顶元素,
//用e返回其值,并返回OK;
//否则返回ERROR
if(S.top == S.base) return ERROR;
e = * - - S.top;
return OK;
} // Pop
//链栈的类型定义如下:
Typedef struct node
{ Elemtype data; //数据域;
struct node * next; //指针域;
}ListNode;
Typedef ListNode * LinkStack;
LinkStack top; //定义一个栈的栈顶指针变量
队列(Queue)是一种先进先出(First in First Out,缩写为FIFO)的线性表。它只允许在表的一端进行插入,而在另一端删除元素。这和我们日常生活中的排队是一致的,最早进入队列的元素最早离开。在队列中,允许插入的一端叫做队尾(rear),允许删除的一端则称为队头(front)。
//— —单链队列——队列的链式存储结构
typedef struct QNode{
QElemType data;
struct QNode *next;
}QNode,*QueuePtr;
typedef struct {
QueuePtr front; //队头指针
QueuePtr rear;//队尾指针
} LinkQueue;
//— — — — —循环队列——队列的顺序存储结构— — — — —
#define MAXQSIZE 100 //最大队列长度
typedef struct {
QElemType *base; //初始化的动态分配存储空间
int front; //头指针,若队列不空,指向队列头元素
int rear; //尾指针,若队列不空,指向队列尾元素的下一个位置
}SqQueue ;
队空条件:Q.front==Q.rear;
队满条件:为避免在队满是队头指针和队尾指针也是重合的情况,规定队列中还有一个空的存储单元时为队满,即为Q.front==(Q.rear+1)MOD maxsize(MOD为取余运算符)。因而,这种循环队列不适合用动态数组作为存储结构。
理想的情况是希望不经过任何比较,一次存取便能得到所查记录,那就必须在记录的存储位置和它的关键字之间建立一个确定的对应关系f,在查找时,只要根据这个对应关系f找到给定值K的像f(K)。若结构中存在关键字和K相等的记录,则必定在f(K)的存储位置上,可直接取得所查记录。在此,我们称这个对应关系f为哈希(Hash)函数,按这个思想建立的表为哈希表。
哈希表的设计过程
(1)明确哈希表的地址空间范围,即确定哈希函数的值域。
(2)选择合理的哈希函数。该函数要保证所有可能的数据记录的哈希地址均在制定的值域内,并使冲突可能性尽量少。
(3)设定处理冲突的办法。
哈希函数的基本构造方法
1、直接定址法 2、数学分析法 3、平方取中法
4、折叠法 5、除留余数法
哈希表中处理冲突的常用方法
1、开放地址法
2、再哈希法
3、链地址法
4、建立一个公共溢出区
一、顺序存储结构
//———二叉树的顺序存储表示————
#define MAX_TREE_SIZE 100, //二叉树的最大结点数
typedef TElemType SqBiTree[MAX_TREE_SIZE];
//0号单元存储根结点 SqBiTree bt;
最优二叉树(赫夫曼树)
有序表的查找
折半查找(Binary Search)的查找过程是:先确定待查记录所在的范围(区间),然后逐步缩小范围直到找到或找不到该记录为止。
折半插入排序 (时间复杂度仍为O(n2))
void BInsertSort (SqList &L){ //对顺序表L作折半插入排序。
for(i=2;i<L.length;++i){
L.r[0]=L.r[i] //L.r[i]暂存到L.r[0]
low=1; high=i-1; //在r[low..high]中折半查找有序插入的位置
while(low<=high ){
m=(low+high)/2 //折半
if LT(L.r[0].key , L.r[m].key) high=m-1; //插入点在低半区
else low=m+1; //插入点在高半区
}//while
for (j=i-1; j>=high+1; --j) L.r[j+1]=L.r[j]; //记录后移
L.r[high+1]=L.r[0]; //插入
}//for
}//BInsertSort
快速排序,选择排序。。。
-----------------------------------------
所以我们还需要可靠的信号处理方式,也就是说当执行某些不可被中断的操作的时候屏蔽掉信号处理。直到这些关键操作完成,再对信号进行处理。以后我会给大家详细的解释可靠信号的操作。
signal的保留是因为还要兼容以前,否则这个函数没用了,新写的代码中不要再继续使用此函数。
Linux在支持新版本的信号安装函数sigation ()以及信号发送函数sigqueue()的同时,仍然支持早期的signal()信号安装函数,支持信号发送函数kill()。 注:不要有这样的误解:由sigqueue()发送、sigaction安装的信号就是可靠的。事实上,可靠信号是指后来添加的新信号(信号值位于 SIGRTMIN及SIGRTMAX之间);不可靠信号是信号值小于SIGRTMIN的信号。信号的可靠与不可靠只与信号值有关,与信号的发送及安装函数无关。目前linux中的signal()是通过sigation()函数实现的,因此,即使通过signal()安装的信号,在信号处理函数的结尾也不必再调用一次信号安装函数。同时,由signal()安装的实时信号支持排队,同样不会丢失。 对于目前linux的两个信号安装函数: signal()及sigaction()来说,它们都不能把SIGRTMIN以前的信号变成可靠信号(都不支持排队,仍有可能丢失,仍然是不可靠信号),而且对SIGRTMIN以后的信号都支持排队。这两个函数的最大区别在于,经过sigaction安装的信号都能传递信息给信号处理函数(对所有信号这一点都成立),而经过signal安装的信号却不能向信号处理函数传递信息。对于信号发送函数来说也是一样的。