1、int a[10]={1,2,3,4,5,6,7,8,9,0};
int *p=&a[1];
則p[6]等於8
2、整數數組清零:bzero(),memset()。
3、sizeof();測試變量所占地址的字節數
4、 main()
{
char *str[]={"ab","cd","ef","gh","ij","kl"};
char *t;
t=(str+4)[-1];
printf("%s",t);
}則顯示"gh"
5、小端:低位字節數據存儲在低地址
大端:高位字節數據存儲在低地址
例如:int a=0x12345678;(a首地址為0x2000)
0x2000 0x2001 0x2002 0x2003
0x12 0x34 0x56 0x78 大端格式
6、異步IO和同步IO區別
如果是同步IO,當一個IO操作執行時,應用程序必須等待,直到此IO執行完,相反,異步IO操作在后台運行,
IO操作和應用程序可以同時運行,提高系統性能,提高IO流量; 在同步文件IO中,線程啟動一個IO操作然后就立即進入等待狀態,直到IO操作完成后才醒來繼續執行,而異步文件IO中,
線程發送一個IO請求到內核,然后繼續處理其他事情,內核完成IO請求后,將會通知線程IO操作完成了。
7、用變量a定義
一個整型數 int a;
一個指向整型數的指針 int *a;
一個指向指針的指針,它指向的指針式指向一個整型數 int **a;
一個有10個整型數的數組 int a[10];
一個有10指針的數組,該指針是指向一個整型數 int *a[10];
一個指向有10個整型數數組的指針 int (*a)[10];
一個指向函數的指針,該函數有一個整型數參數並返回一個整型數 int (*a)(int);
一個有10個指針的數組,該指針指向一個函數,該函數有一個整型數參數並返回一個整型 int (*a[10])(int);
8、int foo(void)
{
int i;
char c=0x80;
i=c;
if(i>0)
return 1;
return 2;
}返回值為2;因為i=c=-128;如果c=0x7f,則i=c=127。
9、a=b*2;a=b/4;a=b%8;a=b/8*8+b%4;a=b*15;效率最高的算法
a=b*2 -> a=b<<1;
a=b/4 -> a=b>>2;
a=b%8 -> a=b&7;
a=b/8*8+b%4 -> a=((b>>3)<<3)+(b&3)
a=b*15 -> a=(b<<4)-b
10、c關鍵字
c的關鍵字共32個
*數據類型關鍵字(12)
char,short,int,long,float,double,unsigned,signed,union,enum,void,struct
*控制語句關鍵字(12)
if,else,switch,case,default,for,do,while,break,continue,goto,return
*存儲類關鍵字(5)
auto,extern,register,static,const
*其他關鍵字(3)
sizeof,typedef,volatile
11、int main(void)
{
unsigned int a = 6;
int b = -20;
char c;
(a+b>6)?(c=1):(c=0);
}則c=1,但a+b=-14;如果a為int類型則c=0。
原來有符號數和無符號數進行比較運算時(==,<,>,<=,>=),有符號數隱式轉換成了無符號數(即底層的補碼不變,但是此數從有符號數變成了無符號數),
比如上面 (a+b)>6這個比較運算,a+b=-14,-14的補碼為1111111111110010。此數進行比較運算時,
被當成了無符號數,它遠遠大於6,所以得到上述結果。
12、給定一個整型變量a,寫兩段代碼,第一個設置a的bit3,第二個清除a的bit,在以上兩個操作中,
要保持其它位不變。
#define BIT3 (0x1<<3)
static int a;
void set_bit3(void)
{
a |= BIT3;
}
void clear_bit3(void)
{
a &= ~BIT3;
}
13、要求設置一絕對地址為0x67a9的整型變量的值為0xaa66。
int *ptr;
ptr = (int *)0x67a9;
*ptr = 0xaa66;(建議用這種)
一個較晦澀的方法是:
*(int * const)(0x67a9) = 0xaa66;
14、中斷是嵌入式系統中重要的組成部分,這導致了很多編譯開發商提供一種擴展—讓標准C支持中斷。
具代表性的是,產生了一個新的關鍵字__interrupt。下面的代碼就使用了__interrupt關鍵字去定義了一個中斷服務子程序(ISR),請評論一下這段代碼的。
__interrupt void compute_area (void)
{
double area = PI * radius * radius;
printf(" Area = %f", area);
return area;
}
ISR不可能有參數和返回值的!
ISR盡量不要使用浮點數處理程序,浮點數的處理程序一般來說是不可重入的,而且是消耗大量CPU時間的!!
printf函數一般也是不可重入的,UART屬於低速設備,printf函數同樣面臨大量消耗CPU時間的問題!
15、評價下面的代碼片斷:
unsigned int zero = 0;
unsigned int compzero = 0xFFFF;
/*1's complement of zero */
對於一個int型不是16位的處理器為說,上面的代碼是不正確的。應編寫如下:
unsigned int compzero = ~0;
16、main()
{
char *ptr;
if ((ptr = (char *)malloc(0)) == NULL)
puts("Got a null pointer");
else
puts("Got a valid pointer");
}
該代碼的輸出是“Got a valid pointer”。還可以*ptr='a';不出現段錯誤
17、Typedef 在C語言中頻繁用以聲明一個已經存在的數據類型的同義字。也可以用預處理器做類似的事。
例如,思考一下下面的例子:
#define dPS struct s *
typedef struct s * tPS;
以上兩種情況的意圖都是要定義dPS 和 tPS 作為一個指向結構s指針。哪種方法更好呢?(如果有的話)為什么?
這是一個非常微妙的問題,任何人答對這個問題(正當的原因)是應當被恭喜的。答案是:typedef更好。思考下面的例子:
dPS p1,p2;
tPS p3,p4;
第一個擴展為
struct s * p1, p2;
上面的代碼定義p1為一個指向結構的指,p2為一個實際的結構,這也許不是你想要的。第二個例子正確地定義了p3 和p4 兩個指針。
18、int a = 5, b = 7, c;
c = a+++b;
則c=12。
19、int main()
{
int j=2;
int i=1;
if(i = 1) j=3;
if(i = 2) j=5;
printf("%d",j);
}
輸出為5;如果再加上if(i=3)j=6;則輸出6。
20、宏定義是在預編譯階段被處理的。
21、Norflash與Nandflash的區別
(1)、NAND閃存的容量比較大
(2)、由於NandFlash沒有掛接在地址總線上,所以如果想用NandFlash作為系統的啟動盤,就需要CPU具備特殊的功能,
如s3c2410在被選擇為NandFlash啟動方式時會在上電時自動讀取NandFlash的4k數據到地址0的SRAM中。
(3)、NAND Flash一般地址線和數據線共用,對讀寫速度有一定影響。NOR Flash閃存數據線和地址線分開,
所以相對而言讀寫速度快一些。
22、反碼:對原碼除符號位外的其余各位逐位取反就是反碼
補碼:負數的補碼就是對反碼加1
正數的原碼、反碼、補碼都一樣
23、pthread_t tid;
pthread_create(&tid,NULL,pthread_func,NULL);//創建線程
pthread_join(tid,NULL);//等待子線程結束,並回收資源
pthread_detach(tid);//與當前進程分離
pthread_exit(NULL);//退出調用線程
pthread_cancel(tid);//取消線程
pthread_mutex mutex=PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_init(&mutex,NULL);//初始化一個互斥鎖
pthread_mutex_lock(&mutex);//對互斥鎖上鎖
pthread_mutex_unlock(&mutex);//對互斥鎖解鎖
sem_t sem;
sem_init(&sem,0,1);//創建信號量並初始化它的值
sem_wait(&sem);//信號量的值減1
sem_post(&sem);//信號量的值加1
24、內存管理MMU的作用
*內存分配和回收
*內存保護
*內存擴充
*地址映射
25、ROM是只讀存儲器,掉電不丟失
RAM是讀寫存儲器,掉電丟失
26、SRAM:CPU的緩存就是SRAM,靜態的隨機存取存儲器,加電情況下,不需要刷新,數據不會丟失
DRAM,動態隨機存取存儲器最為常見的系統內存,需要不斷刷新,才能保存數據
SDRAM:同步動態隨機存儲器,即數據的讀取需要時鍾來同步。
27、signed char 的取值范圍-128~127.
28、編譯和鏈接有什么不同?(如外部符號的處理)
編譯生成的是目標文件(object *.o);
編譯過程中對於外部符號不做任何解釋和處理。外部符號對應的就是“符號”
鏈接生成的是可執行程序
鏈接將會解釋和處理外部符號。外部符號對應的是地址
29、已知strcpy函數的函數原型是:
char *strcpy(char *strDest, const char *strSrc)。其中,strDest是目的字符串,strSrc是源字符串。
不調用C++/C的字符串庫函數,請編寫函數strcpy
char *strcpy(char *strDest, const char *strSrc)
{
int i=0;
if(!(strDest && strSrc))
return;
while(strDest[i++] = *strSrc++);
return strDest;
}
30、strcpy能把strSrc的內容復制到strDest,為什么還要char *類型的返回值?
為了實現鏈式表達式
int len = strlen(strcpy(strDest, strSrc));
31、寫一個“標准”宏MIN,這個宏輸入兩個參數並返回較小的一個
#define MIN(a, b) (a) <= (b) ? (a) : (b)
32、關鍵字static的作用是什么
static用來修飾一個局部的變量的時候,
生命域是全局的
作用域是局部的
static用來修飾一個模塊內的(某一個C的源程序文件)全局變量的時候
生命域不變
作用域減小,只在本模塊內有效
static用來修飾一個函數的時候
作用域減小,只在本模塊內有效
33、說明下面的聲明的含義:
A.
const int a; // a是一個常數
int const a; // a是一個常數
B.
const int *a; // a是一個指向整型常數的指針
int * const a; // a是一個指向整型變量的常指針
int const * a const; // a是一個指向整型常數的常指針
C.
char *strcpy(char *strDest, const char *strSrc);
// 參數在函數內部不會被修改
const int strcmp(char *source, char *dest);
// 函數的返回值不能被修改
const int a = strcmp(xx, yy);
if(strcmp(xx,yy) != 0)
34、說明關鍵字volatile有什么含意,並給出例子。
volatile表示被修飾的符號是易變的。告訴編譯器不要隨便優化我的代碼!!
*一個硬件寄存器
*中斷中用到的變量
*線程之間共享變量
volatile int a = 10;
while((a & 0x01) == 0);
#define P_UART_STATUS ((const volatile unsigned int *)0x88000000);
// volatile表示硬件會修改這個寄存器的內容
// const表示該寄存器只讀,寫無意義
35、printf可以接受多個參數,為什么,請寫出printf的原型。
int printf(const char *fmt, ...);
36、什么是堆棧,簡述為什么需要堆棧?
堆棧是計算機中最常用的一種數據結構,保存數據的一塊連續內存;比如函數的調用是用堆棧實現的。
37、請列舉常用的串行通信方式(兩種以上),並簡述串行通信和並行通信不同之處、優缺點。
異步通信和同步通信;並行速度快,串行口線間干擾小
38、列舉一下你熟悉7層OSI協議中的幾層。說說你最熟悉的一層協議的功能。
應用層,表示層,會話層,傳輸層,網絡層,數據鏈路層,物理層。
39、路由協議:網關-網關協議,外部網關協議,內部網關協議(RIP-1、RIP-IGRP、EIGRP、IS-IS和OSPF)
40、位轉換
位 8 7 6 5 4 3 2 1
數 v8 v7 v6 v5 v4 v3 v2 v1
轉換后:
位 8 7 6 5 4 3 2 1
數 v1 v2 v3 v4 v5 v6 v7 v8
unsigned char bit_reverse(unsigned char c)
{
unsigned char buf = 0;
int bit = 8;
while(bit)
{
bit--;
buf |= ((c & 1) << bit);
c >>=1;
}
return buf;
}
41、字符串倒序
1)、inverted_order(char *p)
{
char *s1,*s2,tem;
s1=p;
s2=s1+strlen(p)-1;
while(s1<s2)
{
tem=*s1;
*s1=*s2;
*s2=tem;
s1++;
s2--;
}
}
2)、inverted_order(char *p)
{
int len = strlen(src);
char *des = (char *)malloc(len + 1);
char *s = &src[len -1];
char *d = des;
while(len-- != 0)
*d++ = *s--;
*d = 0;
free(des);
}
42、引用和指針的區別
(1). 指針是一個實體,而引用僅是個別名;
(2). 引用使用時無需解引用(*),指針需要解引用;
(3). 引用只能在定義時被初始化一次,之后不可變;指針可變;
(4). 引用沒有 const,指針有 const,const 的指針不可變;
(5). 引用不能為空,指針可以為空;
(6). “sizeof 引用”得到的是所指向的變量(對象)的大小,
而“sizeof指針”得到的是指針本身(所指向的變量或對象的地址)的大小;
(7). 指針和引用的自增(++)運算意義不一樣;
43、隊列和棧的區別
隊列是先進先出,只能在一端插入另一端刪除,可以從頭或尾進行遍歷(但不能同時遍歷),
棧是先進后出,只能在同一端插入和刪除,只能從頭部取數據
44、四層模型?七層模型?TCP/IP協議包括?
這7層是:物理層、數據鏈路層、網路層、傳輸層、話路層、表示層和應用層
這4層分別為:應用層、傳輸層、網絡層、鏈路層。
TCP/IP協議族包括(IP)、(ARP)、(RARP)、(ICMP)、(UDP)、(TCP)、(RIP)、Telnet、(SMTP)、DNS等協議。
45、TCP通信建立和結束的過程?端口的作用
三次握手和四次揮手;端口是一個軟件結構,被客戶程序或服務進程用來發送和接收信息。一個端口對應一個16比特的數。服務進程通常使用一個固定的端口。
21端口:21端口主要用於FTP(File Transfer Protocol,文件傳輸協議)服務。 23端口:23端口主要用於Telnet(遠程登錄)服務,是Internet上普遍采用的登錄和仿真程序。
25端口:25端口為SMTP(Simple Mail TransferProtocol,簡單郵件傳輸協議)服務器所開放,
主要用於發送郵件,如今絕大多數郵件服務器都使用該協議。
53端口:53端口為DNS(Domain Name Server,域名服務器)服務器所開放,
主要用於域名解析,DNS服務在NT系統中使用的最為廣泛。
67、68端口:67、68端口分別是為Bootp服務的Bootstrap Protocol Server
(引導程序協議服務端)和Bootstrap Protocol Client(引導程序協議客戶端)開放的端口。
69端口:TFTP是Cisco公司開發的一個簡單文件傳輸協議,類似於FTP。
79端口:79端口是為Finger服務開放的,主要用於查詢遠程主機在線用戶、操作系統類型以及是否緩沖區溢出等用戶的詳細信息。880端口:80端口是為HTTP(HyperText Transport Protocol,超文本傳輸協議)開放的,
這是上網沖浪使用最多的協議,主要用於在WWW(World Wide Web,萬維網)服務上傳輸信息的協議。
99端口:99端口是用於一個名為“Metagram Relay”(亞對策延時)的服務,
該服務比較少見,一般是用不到的。
109、110端口:109端口是為POP2(Post Office Protocol Version 2,郵局協議2)服務開放的,
110端口是為POP3(郵件協議3)服務開放的,POP2、POP3都是主要用於接收郵件的。
111端口:111端口是SUN公司的RPC(Remote Procedure Call,遠程過程調用)服務所開放的端口,
主要用於分布式系統中不同計算機的內部進程通信,RPC在多種網絡服務中都是很重要的組件。
113端口:113端口主要用於Windows的“Authentication Service”(驗證服務)。
119端口:119端口是為“Network News Transfer Protocol”(網絡新聞組傳輸協議,簡稱NNTP)開放的。
135端口:135端口主要用於使用RPC(Remote Procedure Call,遠程過程調用)協議並提供DCOM(分布式組件對象模型)服務。
137端口:137端口主要用於“NetBIOS Name Service”(NetBIOS名稱服務)。
139端口:139端口是為“NetBIOS Session Service”提供的,主要用於提供Windows文件和打印機共享以及Unix中的Samba服務。
143端口:143端口主要是用於“Internet Message Access Protocol”v2(Internet消息訪問協議,簡稱IMAP)。
161端口:161端口是用於“Simple Network Management Protocol”(簡單網絡管理協議,簡稱SNMP)。
443端口:43端口即網頁瀏覽端口,主要是用於HTTPS服務,是提供加密和通過安全端口傳輸的另一種HTTP。
554端口:554端口默認情況下用於“Real Time Streaming Protocol”(實時流協議,簡稱RTSP)。
1024端口:1024端口一般不固定分配給某個服務,在英文中的解釋是“Reserved”(保留)。
1080端口:1080端口是Socks代理服務使用的端口,大家平時上網使用的WWW服務使用的是HTTP協議的代理服務。
1755端口:1755端口默認情況下用於“Microsoft Media Server”(微軟媒體服務器,簡稱MMS)。
4000端口:4000端口是用於大家經常使用的QQ聊天工具的,再細說就是為QQ客戶端開放的端口,QQ服務端使用的端口是8000。
5554端口:在今年4月30日就報道出現了一種針對微軟lsass服務的新蠕蟲病毒——震盪波(Worm.Sasser),該病毒可以利用TCP 5554端口開啟一個FTP服務,主要被用於病毒的傳播。
5632端口:5632端口是被大家所熟悉的遠程控制軟件pcAnywhere所開啟的端口。
8080端口:8080端口同80端口,是被用於WWW代理服務的,可以實現網頁瀏覽。
46、物理地址轉換成IP地址的協議?反之?
地址解析協議(ARP)的作用是將IP地址轉換成物理地址;反地址解析協議(RARP)則負責將物理地址轉換成IP地址。
47、WLAN:無線局域網絡:利用射頻技術進行數據傳輸的系統。
WLAN是指應用無線通信技術將計算機設備互聯起來,構成可以互相通信和實現資源共享的網絡體系。無線局域網本質的特點是不再使用通信電纜將計算機與網絡連接起來,而是通過無線的方式連接,從而使網絡的構建和終端的移動更加靈活。
48、已知數組table,用宏求元素個數。
COUNT(table) (sizeof(table)/sizeof(table[0]));
49、定義一個兩個參數的標准宏MAX,總是輸出最大值。
#define MAX(a,b) ((a)>(b)?(a):(b))
50、什么是平衡二叉樹?
當且僅當兩個子樹的高度差不超過1時,這個樹是平衡二叉樹。
51、全局變量和局部變量的區別。
全局變量,儲存在靜態區.進入main函數之前就被創建.生命周期為整個源程序;
局部變量,在棧中分配.在函數被調用時才被創建.生命周期為函數內。
52、數組與鏈表的區別。
數組中的數據在內存中的按順序存儲的,而鏈表是隨機存儲的!
要訪問數組中的元素可以按下標索引來訪問,速度比較快,如果對他進行插入操作的話, 就得移動很多元素,所以對數組進行插入操作效率很低!由於連表是隨機存儲的,
鏈表在插入,刪除操作上有很高的效率(相對數組),如果要訪問鏈表中的某個元素的話,
那就得從鏈表的頭逐個遍歷,直到找到所需要的元素為止,
所以鏈表的隨機訪問的效率就比數組要低
53、死鎖的四個條件及處理方法。
(1)互斥條件:一個資源每次只能被一個進程使用。
(2) 請求與保持條件:一個進程因請求資源而阻塞時,對已獲得的資源保持不放。
(3)不剝奪條件:進程已獲得的資源,在末使用完之前,不能強行剝奪。
(4)循環等待條件:若干進程之間形成一種頭尾相接的循環等待資源關系。
解決死鎖的方法分為死鎖的預防,避免,檢測與恢復三種
54、進程調度策略。
先進先出算法,最短CPU運行期優先調度算法,輪轉法,多級隊列方法
55、Linux驅動程序流程及功能。
設備驅動程序的功能:
對設備初始化和釋放
把數據從內核傳送到硬件和從硬件讀取數據
讀取應用程序傳送給設備文件的數據和回送應用程序請求的數據
檢測和處理設備出現的錯誤
56、時間換空間、空間換時間的例子。
冒泡排序 --- 時間換空間
快速排序,堆排序 --- 空間換時間
57、MAC層通信協議有哪些?
ISO2110,IEEE802,IEEE802.2
58、關鍵字static的作用是什么?
*在函數體內,一個被聲明為靜態的變量在這一函數被調用過程中維持其值不變(該變量存放在靜態變量區)。
*在模塊內(但在函數體外),一個被聲明為靜態的變量可以被模塊內所用函數訪問,但不能被模塊外其它函數訪問。
它是一個本地的全局變量。
*在模塊內,一個被聲明為靜態的函數只可被這一模塊內的其它函數調用。
那就是,這個函數被限制在聲明它的模塊的本地范圍內使用。
59、參數的傳遞方式有幾種?
1、值傳遞
2、指針傳遞
嚴格來看,只有一種傳遞,值傳遞,指針傳遞也是按值傳遞的,復制的是地址。
60、局部變量能否和全局變量重名?
答:能,局部會屏蔽全局。要用全局變量,需要使用 ":: " 局部變量可以與全局變量同名,在函數內引用這個變量時,會用到同名的局部變量,而不會用到全局變量。
對於有些編譯器而言,在同一個函數內可以定義多個同名的局部變量,比如在兩個循環體內都定義一個同名的局部變量,
而那個局部變量的作用域就在那個循環體內。
61、如何引用一個已經定義過的全局變量?
答:extern 可以用引用頭文件的方式,也可以用extern關鍵字,如果用引用頭文件方式來引用某個在頭文件中聲明的全局變理,
假定你將那個變量寫錯了,那么在編譯期間會報錯,如果你用extern方式引用時,假定你犯了同樣的錯誤,
那么在編譯期間不會報錯,而在連接期間報錯。
62、全局變量可不可以定義在可被多個.C文件包含的頭文件中?為什么? 答:可以,在不同的C文件中以static形式來聲明同名全局變量。 可以在不同的C文件中聲明同名的全局變量,前提是其中只能有一個C文件中對此變量賦初值,此時連接不會出錯
63、語句for( ;1 ;)有什么問題?它是什么意思? 答:和while(1)相同。
64、static全局變量與普通的全局變量有什么區別?static局部變量和普通局部變量有什么區別?static函數與普通函數有什么區別? 全局變量(外部變量)的說明之前再加static 就構成了靜態的全局變量。全局變量本身就是靜態存儲方式,
靜態全局變量當然也是靜態存儲方式。 這兩者在存儲方式上並無不同。
這兩者的區別雖在於非靜態全局變量的作用域是整個源程序, 當一個源程序由多個源文件組成時,
非靜態的全局變量在各個源文件中都是有效的。 而靜態全局變量則限制了其作用域,
即只在定義該變量的源文件內有效。 從以上分析可以看出,把局部變量改變為靜態變量后是改變了它的存儲
方式即改變了它的生存期。把全局變量改變為靜態變量后是改變了它的作用域,
限制了它的使用范圍。static函數與普通函數作用域不同。僅在本文件。只在當前源文件中使用的函數應該說明為內部函數(static)
,內部函數應該在當前源文件中說明和定義。對於可在當前源文件以外使用的函數,應該在一個頭文件中說明,
要使用這些函數的源文件要包含這個頭文件 static全局變量與普通的全局變量有什么區別:
static全局變量只初使化一次,防止在其他文件單元中被引用static局部變量和普通局部變量有什么區別:
static局部變量只被初始化一次,下一次依據上一次結果值; static函數與普通函數有什么區別:
static函數在內存中只有一份,普通函數在每個被調用中維持一份拷貝
65、程序的局部變量存在於(堆棧)中,全局變量存在於(靜態區 )中,動態申請數據存在於( 堆)中。
66、-1,2,7,28,,126請問28和126中間那個數是什么?為什么?
答案應該是4^3-1=63 規律是n^3-1(當n為偶數0,2,4)n^3+1(當n為奇數1,3,5)
67、用兩個棧實現一個隊列的功能?要求給出算法和思路!
設2個棧為A,B, 一開始均為空.
入隊: 將新元素push入棧A;
出隊: (1)判斷棧B是否為空;
(2)如果不為空,則將棧A中所有元素依次pop出並push到棧B;
(3)將棧B的棧頂元素pop出;
68、.軟件測試都有那些種類?
人工測試:個人復查、抽查和會審
機器測試:黑盒測試(針對系統功能的測試 )和白盒測試 (測試函數功能,各函數接口)
69、堆棧溢出一般是由什么原因導致的?
沒有回收垃圾資源。
70、寫出float x 與“零值”比較的if語句。
if(x>0.000001&&x<-0.000001)
71、P地址的編碼分為哪倆部分?
IP地址由兩部分組成,網絡號和主機號。不過是要和“子網掩碼”按位與上之后才能區分哪些是網絡位哪些
是主機位
72、寫一個程序, 要求功能:求出用1,2,5這三個數不同個數組合的和為100的組合個數。
如:100個1是一個組合,5個1加19個5是一個組合。。。。 請用C++語言寫。
答案:最容易想到的算法是:
設x是1的個數,y是2的個數,z是5的個數,number是組合數
注意到0<=x<=100,0<=y<=50,0<=z=20,所以可以編程為:
number=0;
for (x=0; x<=100; x++)
for (y=0; y<=50; y++)
for (z=0; z<=20; z++)
if ((x+2*y+5*z)==100)
number++;
73、內存對齊問題的原因?
平台原因(移植原因):不是所有的硬件平台都能訪問任意地址上的任意數據;
性能原因:數據結構(尤其是棧)應該盡可能地在自然邊界上對齊,因為為了訪問未對齊的內存,處理器需要做兩次內存訪問,
而對齊的內存訪問僅需要一次。
74、比較一下進程和線程的區別?
(1)、調度:線程是CPU調度和分派的基本單位
(2)、擁有資源:
* 進程是系統中程序執行和資源分配的基本單位
* 線程自己一般不擁有資源(除了必不可少的程序計數器,一組寄存器和棧),但他可以去訪問其所屬進程的資源,
如進程代碼,數據段以及系統資源(已打開的文件,I/O設備等)。
(3)系統開銷:
* 同一進程中的多個線程可以共享同一地址空間,因此它們之間的同步和通信的實現也比較簡單
* 在進程切換的時候,涉及到整個當前進程CPU環境的保存以及新被調度運行的進程的CPU環境的設置;
而線程切換只需要保存和設置少量寄存器的內容,並不涉及存儲器管理方面的操作,從而能更有效地使用系統資源和
提高系統吞吐量。
75、main()
{
int a[5]={1,2,3,4,5};
int *ptr=(int *)(&a+1);//&a相當於變成了行指針,加1則變成了下一行首地址
printf("%d,%d",*(a+1),*(ptr-1));
}
*(a+1)就是a[1],*(ptr-1)就是a[4],執行結果是2,5
76、 void getmemory(char *p)
{
p=(char *) malloc(100);
strcpy(p,"hello world");
}
int main( )
{
char *str=NULL;
getmemory(str);
printf("%s/n",str);
free(str);
return 0;
}
程序崩潰,getmemory中的malloc 不能返回動態內存, free()對str操作很危險
77、void GetMemory(char *p)
{
p = (char *)malloc(100);
}
void Test(void)
{
char *str = NULL;
GetMemory(str);
strcpy(str, "hello world");
printf(str);
}
請問運行Test函數會有什么樣的結果?
答:程序崩潰。因為GetMemory並不能傳遞動態內存,Test函數中的 str一直都是 NULL。strcpy(str, "hello world");將使程序崩潰。
void GetMemory2(char **p, int num)
{
*p = (char *)malloc(num);
}
void Test(void)
{
char *str = NULL;
GetMemory(&str, 100);
strcpy(str, "hello");
printf(str);
}
請問運行Test函數會有什么樣的結果?
答:(1)能夠輸出hello
(2)內存泄漏
78、char *GetMemory(void)
{
char p[] = "hello world";
return p;
}
void Test(void)
{
char *str = NULL;
str = GetMemory();
printf(str);
}
請問運行Test函數會有什么樣的結果?
答:可能是亂碼。因為GetMemory返回的是指向“棧內存”的指針,該指針的地址不是 NULL,
但其原現的內容已經被清除,新內容不可知。
79、void Test(void)
{
char *str = (char *) malloc(100);
strcpy(str, “hello”);
free(str);
if(str != NULL)
{
strcpy(str, “world”);
printf(str);
}
}
請問運行Test函數會有什么樣的結果?
答:篡改動態內存區的內容,后果難以預料,非常危險。因為free(str);之后,str成為野指針,
if(str != NULL)語句不起作用。
野指針不是NULL指針,是指向被釋放的或者訪問受限內存指針。
造成原因:指針變量沒有被初始化任何剛創建的指針不會自動成為NULL;
指針被free或delete之后,沒有置NULL;
指針操作超越了變量的作用范圍,比如要返回指向棧內存的指針或引用,因為棧內存在函數結束時會被釋放。
80、unsigned char *p=(unsigned char *)0x0801000
unsigned char *q=(unsigned char *)0x0810000
p+5 =? 0x0801005
q+5 =? 0x0810005
81、進程間通信方式:管道、命名管道、消息隊列、共享內存、信號、信號量、套接字。
(1)、 管道( pipe ):管道是一種半雙工的通信方式,數據只能單向流動,而且只能在具有親緣關系的進程間使用。
進程的親緣關系通常是指父子進程關系。
(2)、有名管道 (named pipe) :有名管道也是半雙工的通信方式,但是它允許無親緣關系進程間的通信。
(3)、信號量( semophore ) :信號量是一個計數器,可以用來控制多個進程對共享資源的訪問。
它常作為一種鎖機制,防止某進程正在訪問共享資源時,其他進程也訪問該資源。
因此,主要作為進程間以及同一進程內不同線程之間的同步手段。
(4)、消息隊列( message queue ) : 消息隊列是由消息的鏈表,存放在內核中並由消息隊列標識符標識。
消息隊列克服了信號傳遞信息少、管道只能承載無格式字節流以及緩沖區大小受限等缺點。
(5)、信號 ( sinal ) : 信號是一種比較復雜的通信方式,用於通知接收進程某個事件已經發生。
(6)、共享內存( shared memory ) :共享內存就是映射一段能被其他進程所訪問的內存,
這段共享內存由一個進程創建,但多個進程都可以訪問。共享內存是最快的 IPC 方式,它是針對其他進程間通信方式運行效率低而專門設計的。它往往與其他通信機制,
如信號兩,配合使用,來實現進程間的同步和通信。
(7)、套接字( socket ) : 套接字也是一種進程間通信機制,與其他通信機制不同的是,它可用於不同及其間的進程通信。
82、宏和函數的優缺點?
(1)、函數調用時,先求出實參表達式的值,然后帶入形參。而使用帶參數的宏只是進行簡單的字符替換。
(2)、函數調用是在程序運行時處理的,分配臨時的內存單元;而宏展開則是在編譯時進行的,在展開時並不分配內存單元,
不進行值的傳遞處理,也沒有“返回值”的概念。
(3)、對函數中的實參和形參都要定義類型,二者的類型要求一致,應進行類型轉換;而宏不存在類型問題,宏名無類型,
它的參數也是無類型,只是一個符號代表,展開時帶入指定的字符即可。宏定義時,字符串可以是任何類型的數據。
(4)、調用函數只可得到一個返回值,而宏定義可以設法得到幾個結果。
(5)、使用宏次數多時,宏展開后源程序長,因為每次展開一次都使程序增長,而函數調用不使源程序變長。
(6)、宏替換不占運行時間,只占編譯時間;而函數調用則占運行時間(分配單元、保留現場、值傳遞、返回)。
83、C和c++的不同
c和c++的一些不同點(從語言本身的角度):
1)c++源於c,c++最重要的特性就是引入了面向對象機制,class關鍵字。
2)c++中,變量可以再任何地方聲明;c中,局部變量只能在函數開頭聲明。
3)c++中,const型常量是編譯時常量;c中,const常量只是只讀的變量。
4)c++有&引用;c沒有
5)c++的struct聲明自動將結構類型名typedef;c中struct的名字只在結構標簽名字空間中,不是作為一種類型出現
6)c語言的main函數可以遞歸調用;c++中則不可以
7)c中,void *可以隱式轉換成其他指針類型;c++中要求現實轉換,否則編譯通不過
84、6.大小端格式問題。
方法一:
void checkCpuMode(void)
{
int i = 0x12345678;
char *cp = (char *)&i;
if(*cp == 0x78)
printf("little endian");
else
printf("big endian\n");
}
方法二:
void checkCpuMode(void)
{
int a = 0x12345678;
if((char)a == 0x12)
printf("big endian\n");
else
printf("little endian\n");
}
方法三:
void checkCpuMode(void)
{
union
{
short s;
char c[sizeof(short)];
}un;
un.s=0x0102;
if(un.[0]==1&&un.c[1]==2)
printf("big endian\n");
else
printf("little endian\n");
}
85、由C/C++編譯的程序占用的內存分為以下幾個部分
1、棧區(stack): 由編譯器自動分配釋放 ,存放函數的參數值,局部變量的值等。其操作方式類似於數據結構中的棧。
2、堆區(heap): 一般由程序員分配釋放,若程序員不釋放,程序結束時可能由OS回收。
注意它與數據結構中的堆是兩回事,分配方式倒是類似於鏈表。
3、全局區(static): 全局變量和靜態變量的存儲是放在一塊的,初始化的全局變量和靜態變量在一塊區域,
未初始化的全局變量和未初始化的靜態變量在相鄰的另一塊區域,程序結束后有系統釋放 。
4、文字常量區: 常量字符串就是放在這里的, 程序結束后由系統釋放。
5、程序代碼區: 存放函數體的二進制代碼。
87、for(m=5;m--;m<0)
{
printf("m=%d\n",m);
}輸出:4、3、2、1、0
88、5["abcdef"]能夠編譯通過,請問編譯后的結果是什么?
printf("%d\n",5["abcdef"]);輸出'f'的ACSII值,如果是4["abcdef"]則輸出'e'的ACSII的值。
89、線程同步的方法:信號量、條件變量、互斥鎖。
90、for(i=0;i<2,i<3,i<4;i++)
printf("%d \n",i); 輸出:0,1,2,3。
100、物理地址,虛擬地址,邏輯地址和總線地址的區別
邏輯地址(Logical Address)是指由程序產生的與段相關的偏移地址部分。
例如,你在進行C語言指針編程中,可以讀取指針變量本身值(&操作),實際上這個值就是邏輯地址,
它是相對於你當前進程數據段的地址,不和絕對物理地址相干。只有在Intel實模式下,
邏輯地址才和物理地址相等(因為實模式沒有分段或分頁機制, Cpu不進行自動地址轉換);
邏輯也就是在Intel 保護模式下程序執行代碼段限長內的偏移地址(假定代碼段、數據段如果完全一樣)。
應用程序員僅需與邏輯地址打交道,而分段和分頁機制對您來說是完全透明的,僅由系統編程人員涉及。
應用程序員雖然自己可以直接操作內存,那也只能在操作系統給你分配的內存段操作。
線性地址(Linear Address)是邏輯地址到物理地址變換之間的中間層。程序代碼會產生邏輯地址,
或者說是段中的偏移地址,加上相應段的基地址就生成了一個線性地址。如果啟用了分頁機制,
那么線性地址可以再經變換以產生一個物理地址。若沒有啟用分頁機制,那么線性地址直接就是物理地址。
Intel 80386的線性地址空間容量為4G(2的32次方即32根地址總線尋址)。
物理地址(Physical Address) 是指出現在CPU外部地址總線上的尋址物理內存的地址信號,是地址變換的最終結果地址。
如果啟用了分頁機制,那么線性地址會使用頁目錄和頁表中的項變換成物理地址。
如果沒有啟用分頁機制,那么線性地址就直接成為物理地址了。
在x86下,外設的i/o地址是獨立的,即有專門的指令訪問外設i/o,i/o地址就是你所說的“總線地址”。
而“物理地址”就是ram地址。在arm中,i/o和ram統一編址,但linux為了統一各個平台,仍然保留這個概念,其實就是物理地址。
101、編寫內核程序中申請內存和編寫應用程序時申請內存有什么區別
應用程序使用C函數庫中的內存分配函數malloc()申請內存內核會為進程使用的代碼和數據空間維護一個當前位置的值brk,
這個值保存在每個進程的數據結構中。它指出了進程代碼和數據(包括動態分配的數據空間)在進程地址空間中的末端位置。
當malloc()函數為程序分配內存時,它會通過系統調用brk()把程序要求新增的空間長度通知內核,
內核代碼從而可以根據malloc()所提供的信息來更新brk的值,但此時並不為新申請的空間映射物理內存頁面。
只有當程序尋址到某個不存在對應物理頁面的地址時,內核才會進行相關物理內存頁面的映射操作。
當用戶使用內存釋放函數free()動態釋放已申請的內存塊時,c庫中的內存管理函數就會把所釋放的內存塊標記為空閑,
以備程序再次申請內存時使用。在這個過程中內核為該進程所分配的這個物理頁面並不會被釋放掉。
只有當進程最終結束時內核才會全面收回已分配和映射到該進程地址空間范圍內的所有物理內存頁面。
102、如何用C語言實現讀寫寄存器變量
#define rBANKCON0 (*(volatile unsigned long *)0x48000004)
rBankCON0 = 0x12;
103、sscanf("123456 ", "%4s", buf); 1234
sscanf("123456 asdfga","%[^ ]", buf); 123456
sscanf("123456aafsdfADDEFF", "%[1-9a-z]", buf); 123456aafsdf
sscanf("123afsdfADJKLJ", "%[^A-Z]", buf); 123afsdf
104、char* s="AAA";
s[0]='B';
printf("%s",s);
有什么錯?
"AAA"是字符串常量。s是指針,指向這個字符串常量,所以聲明s的時候就有問題。
cosnt char* s="AAA";
然后又因為是常量,所以對是s[0]的賦值操作是不合法的。
105、數組a[N],存放了1至N-1個數,其中某個數重復一次。寫一個函數,找出被重復的數字.時間復雜度必須為o(N)函數原型:
int do_dup(int a[],int N) int do_dup(int a[],int N)//a[0]為監視哨
{ {
int i; int temp;
int s; while (a[0]!=a[a[0]])
int num; {
for(i=0;i<N;i++) temp=a[0];
s+=a[i]; a[0]=a[temp];
num=s-N*(N-1)/2;(num即為重復數) a[temp]=temp;
} }
return a[0];
}
106、tcp/udp是屬於哪一層?tcp/udp有何優缺點?
tcp /udp屬於運輸層
TCP 服務提供了數據流傳輸、可靠性、有效流控制、全雙工操作和多路復用技術等。
與 TCP 不同, UDP 並不提供對 IP 協議的可靠機制、流控制以及錯誤恢復功能等。由於 UDP 比較簡單, UDP 頭包含很少的字節,比 TCP 負載消耗少。
tcp: 提供穩定的傳輸服務,有流量控制,缺點是包頭大,冗余性不好
udp: 不提供穩定的服務,包頭小,開銷小
107、 char a = 100;
char b = 150;//10010110//01101010
unsigned char c ;
c = (a < b)? a:b; --》 c=150;
108、應用程序ping發出的是ICMP請求報文
109、在C語言中memcpy和memmove是一樣的嗎?
memmove()與memcpy()一樣都是用來拷貝src所指向內存內容前n個字節到dest所指的地址上,不同是,當src和dest所指的內存區域重疊時,
memmove()仍然可以正確處理,不過執行效率上略慢些。
110、C語言程序代碼優化方法
* 選擇合適的算法和數據結構
* 使用盡量小的數據類型
* 使用自加、自減指令
* 減少運算的強度
求余運算(a=a%8改為a=a&7)
平方運算(a=pow(a,2.0)改為a=a*a)
用移位實現乘除法運算
* 延時函數的自加改為自減
* switch語句中根據發生頻率來進行case排序
111、找出一個字符串中一個最長的連續的數字,並標注出位置和個數。
void main()
{
char input[100];
char output[100] = {0};
int count = 0, maxlen = 0, i = 0;
char *in=input, *out=output,*temp=NULL,*final=NULL;
printf("Please input string(length under 100):\n");
scanf("%s", input);
printf("Input string is %s\n", input);
while(*in!='\0')
{
if(*in>='0'&&*in<='9')
{
count=0;
temp=in;
for(;(*in>='0')&&(*in<='9');in++)
count++;
if (maxlen<count)
{
maxlen=count;
=temp;
}
}
in++;
}
for(i=0; i<maxlen; i++)
*(out++) = *(final++);
*out='\0';
printf("Maxlen is %d\n", maxlen);
printf("Output is %s\n", output);
}
112、寫出螺旋矩陣
void Matrix(int m,int n) //順時針
{
int i,j,a=1;
int s[100][100];
int small = (m<n)?m:n;
int k=small/2;
for(i=0;i<k;i++)
{
for(j=i;j<n-i-1;j++)
s[i][j]=a++;
for(j=i;j<m-i-1;j++)
s[j][n-i-1]=a++;
for(j=n-i-1;j>i;j--)
s[m-i-1][j]=a++;
for(j=m-i-1;j>i;j--)
s[j][i]=a++;
}
if(small & 1)
{
if(m<n)
for(i=k;i<n-k;++i)
s[k][i]=a++;
else
for(i=k;i<m-k;++i)
s[i][k]=a++;
}
for(i=0;i<m;i++)
{
for(j=0;j<n;j++)
printf("=",s[i][j]);
printf("\n");
}
}
113、int *a = (int *)2;
printf("%d",a+3); 答案是2+3*4=14;int類型地址加1 相當於加4個字節
114、main()
{
char a,b,c,d;
scanf("%c%c",&a,&b);
c=getchar();d=getchar();
printf("%c%c%c%c\n",a,b,c,d);
} 輸出:12
3
115、int a[2] = {1, 2};
//指向常量的指針,指針可以變,指針指向的內容不可以變
const int *p = a;//與int const *p = a;等價
p++;//ok
*p = 10;//error
//常指針,指針不可以變,指針指向的內容可以變
int* const p2 = a;
p2++;//error
*p2 = 10;//ok
//指向常量的常指針,都不可以改變
p3++;//error
*p3 = 10;//error
116、#error 預處理指令的作用是,編譯程序時,只要遇到#error 就會生成一個編譯錯誤提
示消息,並停止編譯
117、中斷活動的全過程大致為:
1、中斷請求:中斷事件一旦發生或者中斷條件一旦構成,中斷源提交“申請報告”,
與請求CPU暫時放下目前的工作而轉為中斷源作為專項服務
2、中斷屏蔽:雖然中斷源提交了“申請報告”,但是,是否得到CPU的響應,
還要取決於“申請報告”是否能夠通過2道或者3道“關卡”(中斷屏蔽)送達CPU
(相應的中斷屏蔽位等於1,為關卡放行;反之相應的中斷屏蔽位等於0,為關卡禁止通行);
3、中斷響應:如果一路放行,則CPU響應中斷后,將被打斷的工作斷點記錄下來
(把斷點地址保護到堆棧),掛起“不再受理其他申請報告牌”
(清除全局中斷標志位GIE=0),跳轉到中斷服務子程序
4、保護現場:在處理新任務時可能破壞原有的工作現場,所以需要對工作現場和工作環境進行適當保護;
5、調查中斷源:檢查“申請報告”是由哪個中斷源提交的,以便作出有針對性的服務;
6、中斷處理:開始對查明的中斷源進行有針對性的中斷服務;
7、清除標志:在處理完畢相應的任務之后,需要進行撤消登記(清除中斷標志),以避免造成重復響應;
8、恢復現場:恢復前面曾經被保護起來的工作現場,以便繼續執行被中斷的工作;
9、中斷返回:將被打斷的工作斷點找回來(從堆棧中恢復斷點地址),
並摘下“不再受理其他申請報告牌”(GIE=1),繼續執行原先被打斷的工作。
118、linux進程間通訊的幾種方式的特點和優缺點,和適用場合。分類:
#管道( pipe ):管道是一種半雙工的通信方式,數據只能單向流動,
而且只能在具有親緣關系的進程間使用。進程的親緣關系通常是指父子進程關系。
#有名管道(named pipe) : 有名管道也是半雙工的通信方式,但是它允許無親緣關系進程間的通信。
#信號量( semophore ) : 信號量是一個計數器,可以用來控制多個進程對共享資源的訪問。
它常作為一種鎖機制,防止某進程正在訪問共享資源時,其他進程也訪問該資源。因此,主要作
為進程間以及同一進程內不同線程之間的同步手段。
#消息隊列( message queue ) : 消息隊列是由消息的鏈表,存放在內核中並由消息隊列標識
符標識。消息隊列克服了信號傳遞信息少、管道只能承載無格式字節流以及緩沖區大小受限等缺點。
#信號 ( sinal ) : 信號是一種比較復雜的通信方式,用於通知接收進程某個事件已經發生。
#共享內存( shared memory):共享內存就是映射一段能被其他進程所訪問的內存,
這段共享內存由一個進程創建,但多個進程都可以訪問。共享內存是最快的IPC方式,
它是針對其他進程間通信方式運行效率低而專門設計的。它往往與其他通信機制,
如信號量,配合使用,來實現進程間的同步和通信。
#套接字( socket ) : 套解口也是一種進程間通信機制,與其他通信機制不同的是,
它可用於不同及其間的進程通信。
119、關鍵字volatile有什么含意?並給出三個不同的例子。
一個定義為volatile的變量是說這變量可能會被意想不到地改變,這樣,編譯器就不會去假設
這個變量的值了。精確地說就是,優化器在用到這個變量時必須每次都小心地重新讀取這個變量的值,
而不是使用保存在寄存器里的備份。
下面是volatile變量的幾個例子:
1). 並行設備的硬件寄存器(如:狀態寄存器)
2). 一個中斷服務子程序中會訪問到的非自動變量(Non-automatic variables)
3). 多線程應用中被幾個任務共享的變量 回答不出這個問題的人是不會被雇佣的。我認為這是區分C程序員和嵌入式系統程序員的最基本的問題。嵌入式系統程序員經常同硬件、中斷、RTOS等等打交道,所用這些都要求volatile變量。不懂得volatile內容將會帶來災難。
假設被面試者正確地回答了這是問題(嗯,懷疑這否會是這樣),我將稍微深究一下,
看一下這家伙是不是直正懂得volatile完全的重要性。
1). 一個參數既可以是const還可以是volatile嗎?解釋為什么。
2). 一個指針可以是volatile 嗎?解釋為什么。
3). 下面的函數有什么錯誤:
int square(volatile int *ptr) {
return *ptr * *ptr;
}
下面是答案:
1). 是的。一個例子是只讀的狀態寄存器。它是volatile因為它可能被意想不到地改變。
它是const因為程序不應該試圖去修改它。
2). 是的。盡管這並不很常見。一個例子是當一個中服務子程序修該一個指向一個buffer的指針時。
3). 這段代碼的有個惡作劇。這段代碼的目的是用來返指針*ptr指向值的平方,但是,
由於*ptr指向一個volatile型參數,編譯器將產生類似下面的代碼:
int square(volatile int *ptr) {
int a,b;
a = *ptr;
b = *ptr;
return a * b;
}
由於*ptr的值可能被意想不到地該變,因此a和b可能是不同的。
結果,這段代碼可能返不是你所期望的平方值!正確的代碼如下:
long square(volatile int *ptr) {
int a;
a = *ptr;
return a * a;
}
Volatile 關鍵字告訴編譯器不要持有變量的臨時性拷貝。一般用在多線程程序中,
以避免在其中一個線程操作該變量時,將其拷貝入寄存器。
請看以下情形: A線程將變量復制入寄存器,然后進入循環,反復檢測寄存器的值是否滿足
一定條件(它期待B線程改變變量的值。在此種情況下,當B線程改變了變量的值時,
已改變的值對其在寄存器的值沒有影響。所以A線程進入死循環。
volatile 就是在此種情況下使用。
120、如何防止同時產生大量的線程,方法是使用線程池,線程池具有可以同時提高調度效率和
限制資源使用的好處,線程池中的線程達到最大數時,其他線程就會排隊等候
121、main()
{
char *p1=“name”;
char *p2;
p2=(char*)malloc(20);
memset (p2, 0, 20);
while(*p2++ = *p1++);
printf(“%s\n”,p2);
}
答案:Answer:empty string. 因p2++已經指到了'\0'了;
122、操作系統的內存分配一般有哪幾種方式,各有什么優缺點?
定長和變長。
變長:內存時比較靈活,但是易產生內存碎片。
定長:靈活性差,但分配效率較高,不會產生內存碎片
123、全局變量可不可以定義在可被多個.C文件包含的頭文件中?為什么?
答:可以,在不同的C文件中以static形式來聲明同名全局變量。可以在不同的C文件中聲明同名的全局變量,
前提是其中只能有一個C文件中對此變量賦初值,此時連接不會出錯
124、確定模塊的功能和模塊的接口是在軟件設計的那個隊段完成的?概要設計階段
125、#define N 500
unsigned char count;
for(count=0;count < N;count++)
{
printf("---%d---\n",count);
}死循環,因為unsigned char 最大為255
126、給定結構struct A
{
char t:4; 4位
char k:4; 4位
unsigned short i:8; 8位
unsigned long m; // 偏移2字節保證4字節對齊
}; // 共8字節
127、ICMP(ICMP協議對於網絡安全具有極其重要的意義)功能主要有:
· 偵測遠端主機是否存在。
· 建立及維護路由資料。
· 重導資料傳送路徑。
· 資料流量控制。
單向、雙向鏈表操作、寫一個快速排序算法(原理:找一個基准值,分別將大於和小於基准值的數據放到基准值左右兩邊,即一次划分。由於處在兩邊的數據也是無序的,所以再用同樣的划分方法對左右兩邊的序列進行再次划分,直到划分元素只剩1個時結束,)
/******************************************************************/
1、單向鏈表逆序
LONDE *link_reverse(LNODE *head)
{
LNODE *pb,*pt;
if(head == NULL)
return head;
pb = head->next;
head->next=NULL;
while(pb != NULL)
{
pt = pb->next;
pb->next = head;
head = pb;
pb = pt;
}
return head;
}
2、快速排序
void quick_sort(int num,int start_num,int end_num)
{
if(start_num < end_num)
{
int i = start_num;
int j = end_num;
int temp = num[start_num];
while(i < j)
{
while(i < j && num[j] < temp)
j--;
if(i < j)
num[i++] = num[j];//把小於基准值放在左邊
while(i < j && num[i] >= temp)
i++;
if(i < j)
num[j--] = num[i];//把大於基准值放在右邊
}
num[i] = temp;
quick_sort(num,start_num,i-1);
quick_sort(num,i+1,end_num);
}
}
3、//二分擦找
int binary_search(int array[],int value,int size)
{
int low=0,high=size-1,mid;
while(low<=high) //只要高低不碰頭就繼續二分查找
{
mid=(low+high)/2;
if(value==array[mid]) //比較是不是與中間元素相等
return mid;
else if(value > array[mid]) //每查找一次,就判斷一次所要查找變量所在范圍,並繼續二分
low=mid; //如果大小中間值,下限移到中間的后一個位,上限不變,往高方向二分
else
high=mid; //上限移到中間的前一個位,往低方向二分
}
return -1;
}
/*雙向循環鏈表插入函數*/
TYPE *insert_link(TYPE *head,TYPE *p_in)
{
TYPE *p_mov = head,p_front = head;
if(head == NULL)
{
head = p_in;
p_in->next = head;
p_perior = head;
}
else
{
while((p_in->[] > p_mov->[]) && (p_mov->next != head))
{
p_front = p_mov;
p_mov = p_mov->next;
}
if(p_in->[] <= p_mov->[])
{
if(head == p_mov)
{
p_in->prior = head->prior;
head->prior->next = p_in;
p_in->next = p_mov;
p_mov->prior = p_in;
head = p_in;
}
else
{
pf->next = p_in;
p_in->prior = p_front;
p_in->next = p_mov;
p_mov->prior = p_in;
}
}
else
{
p_mov->next = p_in;
p_in->prior = p_mov;
p_in->next = head;
head->prior = p_in;
}
}
return head;
}
/*雙向鏈表刪除函數*/
TYPE *delete_link(TYPE *head,int num)
{
TYPE *p_mov = head,p_front = head;
if(head == NULL)
printf("Not link\n");
while((p_mov->num != num) && (p_mov->next != head))
{
p_front = p_mov;
p_mov = p_mov->next;
}
if(p_mov->num == num)
{
if(p_mov == head)
{
if(p_mov->next == head && p_mov->prior == head)
{
free(pb);
head =NULL;
return head;
}
head->next->prior = head->prior;
head->prior->next = head->next;
head = head->next;
}
else
{
p_front->next = p_mov->next;
p_mov->next->prior = p_front;
}
free(p_mov);
printf("The node is delete\n");
}
else
{
printf("The node not been found\n");
}
return head;
}