嵌入式面試題

一、int a[10]={1,2,3,4,5,6,7,8,9,0};
   int *p=&a[1];
   則p[6]等於8
二、整數數組清零:bzero(),memset()。
三、sizeof();測試變量所佔地址的字節數
四、 main() 
 { 
  char *str[]={"ab","cd","ef","gh","ij","kl"}; 
  char *t; 
  t=(str+4)[-1]; 
  printf("%s",t); 
 }則顯示"gh"
五、小端:低位字節數據存儲在低地址
 大端:高位字節數據存儲在低地址
 例如:int a=0x12345678;(a首地址爲0x2000)
 0x2000  0x2001  0x2002  0x2003
  0x12    0x34    0x56    0x78      大端格式
六、異步IO和同步IO區別
 若是是同步IO,當一個IO操做執行時,應用程序必須等待,直到此IO執行完,相反,異步IO操做在後臺運行,
 IO操做和應用程序能夠同時運行,提升系統性能,提升IO流量; 在同步文件IO中,線程啓動一個IO操做而後就當即進入等待狀態,直到IO操做完成後才醒來繼續執行,而異步文件IO中,
 線程發送一個IO請求到內核,而後繼續處理其餘事情,內核完成IO請求後,將會通知線程IO操做完成了。
七、用變量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);
八、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。
九、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
十、c關鍵字node

 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
十一、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,因此獲得上述結果。
十二、給定一個整型變量a,寫兩段代碼,第一個設置a的bit3,第二個清除a的bit,在以上兩個操做中,
 要保持其它位不變。
 #define BIT3 (0x1<<3)
  static int a;
  void set_bit3(void)
  {
   a |= BIT3;
  }
  void clear_bit3(void)
  {
   a &= ~BIT3;
  }
1三、要求設置一絕對地址爲0x67a9的整型變量的值爲0xaa66。
  int *ptr;
    ptr = (int *)0x67a9;
     *ptr = 0xaa66;(建議用這種)
  
    一個較晦澀的方法是:
    *(int * const)(0x67a9) = 0xaa66;
1四、中斷是嵌入式系統中重要的組成部分,這致使了不少編譯開發商提供一種擴展—讓標準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時間的問題!
1五、評價下面的代碼片段:
  
  unsigned int zero = 0;
  unsigned int compzero = 0xFFFF;
  /*1's complement of zero */
  對於一個int型不是16位的處理器爲說,上面的代碼是不正確的。應編寫以下:
  unsigned int compzero = ~0;
1六、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';不出現段錯誤
1七、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 兩個指針。
1八、int a = 5, b = 7, c;
  c = a+++b;
 則c=12。
1九、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、宏定義是在預編譯階段被處理的。
2一、Norflash與Nandflash的區別
 (1)、NAND閃存的容量比較大
 (2)、因爲NandFlash沒有掛接在地址總線上,因此若是想用NandFlash做爲系統的啓動盤,就須要CPU具有特殊的功能,
 如s3c2410在被選擇爲NandFlash啓動方式時會在上電時自動讀取NandFlash的4k數據到地址0的SRAM中。
 (3)、NAND Flash通常地址線和數據線共用,對讀寫速度有必定影響。NOR Flash閃存數據線和地址線分開,
    因此相對而言讀寫速度快一些。
2二、反碼:對原碼除符號位外的其他各位逐位取反就是反碼
 補碼:負數的補碼就是對反碼加1
 正數的原碼、反碼、補碼都同樣
2三、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
2四、內存管理MMU的做用
  *內存分配和回收
  *內存保護
  *內存擴充
  *地址映射 
2五、ROM是隻讀存儲器,掉電不丟失
 RAM是讀寫存儲器,掉電丟失
2六、SRAM:CPU的緩存就是SRAM,靜態的隨機存取存儲器,加電狀況下,不須要刷新,數據不會丟失
 DRAM,動態隨機存取存儲器最爲常見的系統內存,須要不斷刷新,才能保存數據
 SDRAM:同步動態隨機存儲器,即數據的讀取須要時鐘來同步。
2七、signed char 的取值範圍-128~127.
2八、編譯和連接有什麼不一樣?(如外部符號的處理)
 編譯生成的是目標文件(object  *.o);
 編譯過程當中對於外部符號不作任何解釋和處理。外部符號對應的就是「符號」linux

 連接生成的是可執行程序
 連接將會解釋和處理外部符號。外部符號對應的是地址
2九、已知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));
3一、寫一個「標準」宏MIN,這個宏輸入兩個參數並返回較小的一個
 #define MIN(a, b) (a) <= (b) ? (a) : (b)
3二、關鍵字static的做用是什麼
 static用來修飾一個局部的變量的時候,
  生命域是全局的
  做用域是局部的c++

 static用來修飾一個模塊內的(某一個C的源程序文件)全局變量的時候
  生命域不變
  做用域減少,只在本模塊內有效程序員

 static用來修飾一個函數的時候
  做用域減少,只在本模塊內有效面試

3三、說明下面的聲明的含義:
  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)
3四、說明關鍵字volatile有什麼含意,並給出例子。
 volatile表示被修飾的符號是易變的。告訴編譯器不要隨便優化個人代碼!!
 *一個硬件寄存器
 *中斷中用到的變量
 *線程之間共享變量
 volatile int a = 10;
 while((a & 0x01) == 0);
 #define P_UART_STATUS ((const volatile unsigned int *)0x88000000);
       // volatile表示硬件會修改這個寄存器的內容
       // const表示該寄存器只讀,寫無心義
3五、printf能夠接受多個參數,爲何,請寫出printf的原型。
 int printf(const char *fmt, ...);
3六、什麼是堆棧,簡述爲何須要堆棧?
 堆棧是計算機中最經常使用的一種數據結構,保存數據的一塊連續內存;好比函數的調用是用堆棧實現的。
3七、請列舉經常使用的串行通訊方式(兩種以上),並簡述串行通訊和並行通訊不一樣之處、優缺點。
 異步通訊和同步通訊;並行速度快,串行口線間干擾小
3八、列舉一下你熟悉7層OSI協議中的幾層。說說你最熟悉的一層協議的功能。
    應用層,表示層,會話層,傳輸層,網絡層,數據鏈路層,物理層。
3九、路由協議:網關-網關協議,外部網關協議,內部網關協議(RIP-一、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;
 }
4一、字符串倒序
 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);
  }
4二、引用和指針的區別
  (1). 指針是一個實體,而引用僅是個別名;
   (2). 引用使用時無需解引用(*),指針須要解引用;
   (3). 引用只能在定義時被初始化一次,以後不可變;指針可變;
   (4). 引用沒有 const,指針有 const,const 的指針不可變;
   (5). 引用不能爲空,指針能夠爲空;
   (6). 「sizeof 引用」獲得的是所指向的變量(對象)的大小,
    而「sizeof指針」獲得的是指針自己(所指向的變量或對象的地址)的大小;
   (7). 指針和引用的自增(++)運算意義不同;
4三、隊列和棧的區別
 隊列是先進先出,只能在一端插入另外一端刪除,能夠從頭或尾進行遍歷(但不能同時遍歷),
 棧是先進後出,只能在同一端插入和刪除,只能從頭部取數據
4四、四層模型?七層模型?TCP/IP協議包括?
 這7層是:物理層、數據鏈路層、網路層、傳輸層、話路層、表示層和應用層
 這4層分別爲:應用層、傳輸層、網絡層、鏈路層。 
 TCP/IP協議族包括(IP)、(ARP)、(RARP)、(ICMP)、(UDP)、(TCP)、(RIP)、Telnet、(SMTP)、DNS等協議。
4五、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系統中使用的最爲普遍。  
    6七、68端口:6七、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」(亞對策延時)的服務,
    該服務比較少見,通常是用不到的。  
    10九、110端口:109端口是爲POP2(Post Office Protocol Version 2,郵局協議2)服務開放的,
    110端口是爲POP3(郵件協議3)服務開放的,POP二、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代理服務的,能夠實現網頁瀏覽。
4六、物理地址轉換成IP地址的協議?反之?
 地址解析協議(ARP)的做用是將IP地址轉換成物理地址;反地址解析協議(RARP)則負責將物理地址轉換成IP地址。
4七、WLAN:無線局域網絡:利用射頻技術進行數據傳輸的系統。
   WLAN是指應用無線通訊技術將計算機設備互聯起來,構成能夠互相通訊和實現資源共享的網絡體系。無線局域網本質的特色是再也不使用通訊電纜將計算機與網絡鏈接起來,而是經過無線的方式鏈接,從而使網絡的構建和終端的移動更加靈活。編程

4八、已知數組table,用宏求元素個數。
  COUNT(table)  (sizeof(table)/sizeof(table[0]));數組

4九、定義一個兩個參數的標準宏MAX,老是輸出最大值。
  #define  MAX(a,b)  ((a)>(b)?(a):(b))
50、什麼是平衡二叉樹?
 當且僅當兩個子樹的高度差不超過1時,這個樹是平衡二叉樹。
5一、全局變量和局部變量的區別。
  全局變量,儲存在靜態區.進入main函數以前就被建立.生命週期爲整個源程序; 
 局部變量,在棧中分配.在函數被調用時才被建立.生命週期爲函數內。
5二、數組與鏈表的區別。
  數組中的數據在內存中的按順序存儲的,而鏈表是隨機存儲的!
 要訪問數組中的元素能夠按下標索引來訪問,速度比較快,若是對他進行插入操做的話, 就得移動不少元素,因此對數組進行插入操做效率很低!因爲連表是隨機存儲的,
 鏈表在插入,刪除操做上有很高的效率(相對數組),若是要訪問鏈表中的某個元素的話,
 那就得從鏈表的頭逐個遍歷,直到找到所須要的元素爲止,
 因此鏈表的隨機訪問的效率就比數組要低  
5三、死鎖的四個條件及處理方法。
  (1)互斥條件:一個資源每次只能被一個進程使用。    
 (2) 請求與保持條件:一個進程因請求資源而阻塞時,對已得到的資源保持不放。 
    (3)不剝奪條件:進程已得到的資源,在末使用完以前,不能強行剝奪。   
    (4)循環等待條件:若干進程之間造成一種頭尾相接的循環等待資源關係。  
      解決死鎖的方法分爲死鎖的預防,避免,檢測與恢復三種 
5四、進程調度策略。
  先進先出算法,最短CPU運行期優先調度算法,輪轉法,多級隊列方法
5五、Linux驅動程序流程及功能。
  設備驅動程序的功能:
  對設備初始化和釋放
  把數據從內核傳送到硬件和從硬件讀取數據
  讀取應用程序傳送給設備文件的數據和回送應用程序請求的數據
  檢測和處理設備出現的錯誤
5六、時間換空間、空間換時間的例子。
  冒泡排序 --- 時間換空間
  快速排序,堆排序 --- 空間換時間  
5七、MAC層通訊協議有哪些?
  ISO2110,IEEE802,IEEE802.2  
5八、關鍵字static的做用是什麼?
 *在函數體內,一個被聲明爲靜態的變量在這一函數被調用過程當中維持其值不變(該變量存放在靜態變量區)。
    *在模塊內(但在函數體外),一個被聲明爲靜態的變量能夠被模塊內所用函數訪問,但不能被模塊外其它函數訪問。
     它是一個本地的全局變量。
    *在模塊內,一個被聲明爲靜態的函數只可被這一模塊內的其它函數調用。
  那就是,這個函數被限制在聲明它的模塊的本地範圍內使用。
5九、參數的傳遞方式有幾種?
 一、值傳遞
    二、指針傳遞
    嚴格來看,只有一種傳遞,值傳遞,指針傳遞也是按值傳遞的,複製的是地址。
60、局部變量可否和全局變量重名?    
   答:能,局部會屏蔽全局。要用全局變量,須要使用 ":: "  局部變量能夠與全局變量同名,在函數內引用這個變量時,會用到同名的局部變量,而不會用到全局變量。
   對於有些編譯器而言,在同一個函數內能夠定義多個同名的局部變量,好比在兩個循環體內都定義一個同名的局部變量,
   而那個局部變量的做用域就在那個循環體內。 
6一、如何引用一個已經定義過的全局變量?    
   答:extern 能夠用引用頭文件的方式,也能夠用extern關鍵字,若是用引用頭文件方式來引用某個在頭文件中聲明的全局變理,
   假定你將那個變量寫錯了,那麼在編譯期間會報錯,若是你用extern方式引用時,假定你犯了一樣的錯誤,
   那麼在編譯期間不會報錯,而在鏈接期間報錯。 
6二、全局變量可不能夠定義在可被多個.C文件包含的頭文件中?爲何?    答:能夠,在不一樣的C文件中以static形式來聲明同名全局變量。    能夠在不一樣的C文件中聲明同名的全局變量,前提是其中只能有一個C文件中對此變量賦初值,此時鏈接不會出錯  
6三、語句for(   ;1   ;)有什麼問題?它是什麼意思?    答:和while(1)相同。緩存

6四、static全局變量與普通的全局變量有什麼區別?static局部變量和普通局部變量有什麼區別?static函數與普通函數有什麼區別?    全局變量(外部變量)的說明以前再加static   就構成了靜態的全局變量。全局變量自己就是靜態存儲方式,   
    靜態全局變量固然也是靜態存儲方式。   這二者在存儲方式上並沒有不一樣。
    這二者的區別雖在於非靜態全局變量的做用域是整個源程序,   當一個源程序由多個源文件組成時,
    非靜態的全局變量在各個源文件中都是有效的。   而靜態全局變量則限制了其做用域,  
  即只在定義該變量的源文件內有效。 從以上分析能夠看出,把局部變量改變爲靜態變量後是改變了它的存儲
 方式即改變了它的生存期。把全局變量改變爲靜態變量後是改變了它的做用域,   
 限制了它的使用範圍。static函數與普通函數做用域不一樣。僅在本文件。只在當前源文件中使用的函數應該說明爲內部函數(static)
 ,內部函數應該在當前源文件中說明和定義。對於可在當前源文件之外使用的函數,應該在一個頭文件中說明,
 要使用這些函數的源文件要包含這個頭文件 static全局變量與普通的全局變量有什麼區別:
 static全局變量只初使化一次,防止在其餘文件單元中被引用static局部變量和普通局部變量有什麼區別:
 static局部變量只被初始化一次,下一次依據上一次結果值; static函數與普通函數有什麼區別:
 static函數在內存中只有一份,普通函數在每一個被調用中維持一份拷貝
6五、程序的局部變量存在於(堆棧)中,全局變量存在於(靜態區   )中,動態申請數據存在於(   堆)中。
6六、-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) 
6七、用兩個棧實現一個隊列的功能?要求給出算法和思路!    
    設2個棧爲A,B, 一開始均爲空. 
 入隊: 將新元素push入棧A;    
 出隊: (1)判斷棧B是否爲空;    
       (2)若是不爲空,則將棧A中全部元素依次pop出並push到棧B;    
    (3)將棧B的棧頂元素pop出;
6八、.軟件測試都有那些種類?  
  人工測試:我的複查、抽查和會審 
  機器測試:黑盒測試(針對系統功能的測試 )和白盒測試 (測試函數功能,各函數接口) 
6九、堆棧溢出通常是由什麼緣由致使的?
      沒有回收垃圾資源。
70、寫出float x 與「零值」比較的if語句。
      if(x>0.000001&&x<-0.000001)
7一、P地址的編碼分爲哪倆部分?
     IP地址由兩部分組成,網絡號和主機號。不過是要和「子網掩碼」按位與上以後才能區分哪些是網絡位哪些
     是主機位
7二、寫一個程序, 要求功能:求出用1,2,5這三個數不一樣個數組合的和爲100的組合個數。
   如:100個1是一個組合,5個1加19個5是一個組合。。。。 請用C++語言寫。sass

 答案:最容易想到的算法是:
 設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++;
7三、內存對齊問題的緣由?
 平臺緣由(移植緣由):不是全部的硬件平臺都能訪問任意地址上的任意數據;
 性能緣由:數據結構(尤爲是棧)應該儘量地在天然邊界上對齊,由於爲了訪問未對齊的內存,處理器須要作兩次內存訪問,
     而對齊的內存訪問僅須要一次。
7四、比較一下進程和線程的區別?
 (1)、調度:線程是CPU調度和分派的基本單位
 (2)、擁有資源:
  *  進程是系統中程序執行和資源分配的基本單位
  *  線程本身通常不擁有資源(除了必不可少的程序計數器,一組寄存器和棧),但他能夠去訪問其所屬進程的資源,
     如進程代碼,數據段以及系統資源(已打開的文件,I/O設備等)。
 (3)系統開銷:
  *  同一進程中的多個線程能夠共享同一地址空間,所以它們之間的同步和通訊的實現也比較簡單
  *  在進程切換的時候,涉及到整個當前進程CPU環境的保存以及新被調度運行的進程的CPU環境的設置;
     而線程切換隻須要保存和設置少許寄存器的內容,並不涉及存儲器管理方面的操做,從而能更有效地使用系統資源和
     提升系統吞吐量。
7五、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
7六、 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操做很危險
7七、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)內存泄漏
7八、char *GetMemory(void)
 { 
  char p[] = "hello world";
  return p;
 }
 void Test(void)
 {
  char *str = NULL;
  str = GetMemory(); 
  printf(str);
 }
 請問運行Test函數會有什麼樣的結果?
 答:多是亂碼。由於GetMemory返回的是指向「棧內存」的指針,該指針的地址不是 NULL,
 但其原現的內容已經被清除,新內容不可知。
7九、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
8一、進程間通訊方式:管道、命名管道、消息隊列、共享內存、信號、信號量、套接字。
 (1)、 管道( pipe ):管道是一種半雙工的通訊方式,數據只能單向流動,並且只能在具備親緣關係的進程間使用。
       進程的親緣關係一般是指父子進程關係。
 (2)、有名管道 (named pipe) :有名管道也是半雙工的通訊方式,可是它容許無親緣關係進程間的通訊。
 (3)、信號量( semophore ) :信號量是一個計數器,能夠用來控制多個進程對共享資源的訪問。
      它常做爲一種鎖機制,防止某進程正在訪問共享資源時,其餘進程也訪問該資源。
      所以,主要做爲進程間以及同一進程內不一樣線程之間的同步手段。
 (4)、消息隊列( message queue ) : 消息隊列是由消息的鏈表,存放在內核中並由消息隊列標識符標識。
      消息隊列克服了信號傳遞信息少、管道只能承載無格式字節流以及緩衝區大小受限等缺點。
 (5)、信號 ( sinal ) : 信號是一種比較複雜的通訊方式,用於通知接收進程某個事件已經發生。
 (6)、共享內存( shared memory ) :共享內存就是映射一段能被其餘進程所訪問的內存,
      這段共享內存由一個進程建立,但多個進程均可以訪問。共享內存是最快的 IPC 方式,它是針對其餘進程間通訊方式運行效率低而專門設計的。它每每與其餘通訊機制,
      如信號兩,配合使用,來實現進程間的同步和通訊。
 (7)、套接字( socket ) : 套接字也是一種進程間通訊機制,與其餘通訊機制不一樣的是,它可用於不一樣及其間的進程通訊。 
8二、宏和函數的優缺點?
 (1)、函數調用時,先求出實參表達式的值,而後帶入形參。而使用帶參數的宏只是進行簡單的字符替換。
 (2)、函數調用是在程序運行時處理的,分配臨時的內存單元;而宏展開則是在編譯時進行的,在展開時並不分配內存單元,
   不進行值的傳遞處理,也沒有「返回值」的概念。
 (3)、對函數中的實參和形參都要定義類型,兩者的類型要求一致,應進行類型轉換;而宏不存在類型問題,宏名無類型,
   它的參數也是無類型,只是一個符號表明,展開時帶入指定的字符便可。宏定義時,字符串能夠是任何類型的數據。
 (4)、調用函數只可獲得一個返回值,而宏定義能夠設法獲得幾個結果。
 (5)、使用宏次數多時,宏展開後源程序長,由於每次展開一次都使程序增加,而函數調用不使源程序變長。
 (6)、宏替換不佔運行時間,只佔編譯時間;而函數調用則佔運行時間(分配單元、保留現場、值傳遞、返回)。
8三、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++中要求現實轉換,不然編譯通不過
8四、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");
 }
8五、由C/C++編譯的程序佔用的內存分爲如下幾個部分 
 一、棧區(stack): 由編譯器自動分配釋放 ,存放函數的參數值,局部變量的值等。其操做方式相似於數據結構中的棧。 
 二、堆區(heap): 通常由程序員分配釋放,若程序員不釋放,程序結束時可能由OS回收。
                 注意它與數據結構中的堆是兩回事,分配方式卻是相似於鏈表。 
 三、全局區(static): 全局變量和靜態變量的存儲是放在一塊的,初始化的全局變量和靜態變量在一塊區域,
                    未初始化的全局變量和未初始化的靜態變量在相鄰的另外一塊區域,程序結束後有系統釋放 。 
 四、文字常量區: 常量字符串就是放在這裏的, 程序結束後由系統釋放。 
 五、程序代碼區: 存放函數體的二進制代碼。
8七、for(m=5;m--;m<0)
 {
  printf("m=%d\n",m);
 }輸出:四、三、二、一、0
8八、5["abcdef"]可以編譯經過,請問編譯後的結果是什麼?
 printf("%d\n",5["abcdef"]);輸出'f'的ACSII值,若是是4["abcdef"]則輸出'e'的ACSII的值。
8九、線程同步的方法:信號量、條件變量、互斥鎖。
90、for(i=0;i<2,i<3,i<4;i++)
  printf("%d \n",i);     輸出:0,1,2,3。

100、物理地址,虛擬地址,邏輯地址和總線地址的區別
     邏輯地址(Logical Address)是指由程序產生的與段相關的偏移地址部分。
 例如,你在進行C語言指針編程中,能夠讀取指針變量自己值(&amp;操做),實際上這個值就是邏輯地址,
 它是相對於你當前進程數據段的地址,不和絕對物理地址相干。只有在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爲了統一各個平臺,仍然保留這個概念,其實就是物理地址。  
10一、編寫內核程序中申請內存和編寫應用程序時申請內存有什麼區別
     應用程序使用C函數庫中的內存分配函數malloc()申請內存內核會爲進程使用的代碼和數據空間維護一個當前位置的值brk,
 這個值保存在每一個進程的數據結構中。它指出了進程代碼和數據(包括動態分配的數據空間)在進程地址空間中的末端位置。
 當malloc()函數爲程序分配內存時,它會經過系統調用brk()把程序要求新增的空間長度通知內核,
 內核代碼從而能夠根據malloc()所提供的信息來更新brk的值,但此時並不爲新申請的空間映射物理內存頁面。
 只有當程序尋址到某個不存在對應物理頁面的地址時,內核纔會進行相關物理內存頁面的映射操做。
     當用戶使用內存釋放函數free()動態釋放已申請的內存塊時,c庫中的內存管理函數就會把所釋放的內存塊標記爲空閒,
 以備程序再次申請內存時使用。在這個過程當中內核爲該進程所分配的這個物理頁面並不會被釋放掉。
 只有當進程最終結束時內核纔會全面收回已分配和映射到該進程地址空間範圍內的全部物理內存頁面。
10二、如何用C語言實現讀寫寄存器變量
 #define rBANKCON0  (*(volatile unsigned long *)0x48000004) 
 rBankCON0 = 0x12; 
10三、sscanf("123456 ", "%4s", buf);                     1234
 sscanf("123456 asdfga","%[^ ]", buf);               123456
    sscanf("123456aafsdfADDEFF", "%[1-9a-z]", buf);     123456aafsdf
    sscanf("123afsdfADJKLJ", "%[^A-Z]", buf);          123afsdf
10四、char* s="AAA";
 s[0]='B';
 printf("%s",s);
 有什麼錯?
 "AAA"是字符串常量。s是指針,指向這個字符串常量,因此聲明s的時候就有問題。
 cosnt char* s="AAA";
 而後又由於是常量,因此對是s[0]的賦值操做是不合法的。 
10五、數組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];
              }
10六、tcp/udp是屬於哪一層?tcp/udp有何優缺點?
 tcp /udp屬於運輸層
 TCP 服務提供了數據流傳輸、可靠性、有效流控制、全雙工操做和多路複用技術等。
 與 TCP 不一樣, UDP 並不提供對 IP 協議的可靠機制、流控制以及錯誤恢復功能等。因爲 UDP 比較簡單, UDP 頭包含不多的字節,比 TCP 負載消耗少。
 tcp: 提供穩定的傳輸服務,有流量控制,缺點是包頭大,冗餘性很差
 udp: 不提供穩定的服務,包頭小,開銷小
10七、 char a = 100;
   char b =  150;//10010110//01101010
   unsigned char c ;
      c = (a < b)? a:b;   --》 c=150;
10八、應用程序ping發出的是ICMP請求報文
10九、在C語言中memcpy和memmove是同樣的嗎?
 memmove()與memcpy()同樣都是用來拷貝src所指向內存內容前n個字節到dest所指的地址上,不一樣是,當src和dest所指的內存區域重疊時,
 memmove()仍然能夠正確處理,不過執行效率上略慢些。
1十、C語言程序代碼優化方法
  * 選擇合適的算法和數據結構
  * 使用盡可能小的數據類型
  * 使用自加、自減指令
  * 減小運算的強度
   求餘運算(a=a%8改成a=a&7)
   平方運算(a=pow(a,2.0)改成a=a*a)
   用移位實現乘除法運算
  * 延時函數的自加改成自減
  * switch語句中根據發生頻率來進行case排序
 
1十一、找出一個字符串中一個最長的連續的數字,並標註出位置和個數。
 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);
}
1十二、寫出螺旋矩陣
 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");
  }
 }
11三、int *a = (int *)2;
  printf("%d",a+3); 答案是2+3*4=14;int類型地址加1 至關於加4個字節
11四、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
11五、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
11六、#error 預處理指令的做用是,編譯程序時,只要遇到#error 就會生成一個編譯錯誤提
  示消息,並中止編譯
11七、中斷活動的全過程大體爲:
 一、中斷請求:中斷事件一旦發生或者中斷條件一旦構成,中斷源提交「申請報告」,
   與請求CPU暫時放下目前的工做而轉爲中斷源做爲專項服務
 二、中斷屏蔽:雖然中斷源提交了「申請報告」,可是,是否獲得CPU的響應,
   還要取決於「申請報告」是否可以經過2道或者3道「關卡」(中斷屏蔽)送達CPU
  (相應的中斷屏蔽位等於1,爲關卡放行;反之相應的中斷屏蔽位等於0,爲關卡禁止通行);
 三、中斷響應:若是一路放行,則CPU響應中斷後,將被打斷的工做斷點記錄下來
  (把斷點地址保護到堆棧),掛起「再也不受理其餘申請報告牌」
  (清除全局中斷標誌位GIE=0),跳轉到中斷服務子程序
 四、保護現場:在處理新任務時可能破壞原有的工做現場,因此須要對工做現場和工做環境進行適當保護;
 五、調查中斷源:檢查「申請報告」是由哪一個中斷源提交的,以便做出有針對性的服務;
 六、中斷處理:開始對查明的中斷源進行有針對性的中斷服務;
 七、清除標誌:在處理完畢相應的任務以後,須要進行撤消登記(清除中斷標誌),以免形成重複響應;
 八、恢復現場:恢復前面曾經被保護起來的工做現場,以便繼續執行被中斷的工做;
 九、中斷返回:將被打斷的工做斷點找回來(從堆棧中恢復斷點地址),
 並摘下「再也不受理其餘申請報告牌」(GIE=1),繼續執行原先被打斷的工做。   
11八、linux進程間通信的幾種方式的特色和優缺點,和適用場合。分類:
 #管道( pipe ):管道是一種半雙工的通訊方式,數據只能單向流動,
    並且只能在具備親緣關係的進程間使用。進程的親緣關係一般是指父子進程關係。  
 #有名管道(named pipe) : 有名管道也是半雙工的通訊方式,可是它容許無親緣關係進程間的通訊。 
 #信號量( semophore ) : 信號量是一個計數器,能夠用來控制多個進程對共享資源的訪問。
   它常做爲一種鎖機制,防止某進程正在訪問共享資源時,其餘進程也訪問該資源。所以,主要做
   爲進程間以及同一進程內不一樣線程之間的同步手段。  
 #消息隊列( message queue ) : 消息隊列是由消息的鏈表,存放在內核中並由消息隊列標識
   符標識。消息隊列克服了信號傳遞信息少、管道只能承載無格式字節流以及緩衝區大小受限等缺點。
 #信號 ( sinal ) : 信號是一種比較複雜的通訊方式,用於通知接收進程某個事件已經發生。 
 #共享內存( shared memory):共享內存就是映射一段能被其餘進程所訪問的內存,
   這段共享內存由一個進程建立,但多個進程均可以訪問。共享內存是最快的IPC方式,
   它是針對其餘進程間通訊方式運行效率低而專門設計的。它每每與其餘通訊機制,
   如信號量,配合使用,來實現進程間的同步和通訊。 
 #套接字( socket ) : 套解口也是一種進程間通訊機制,與其餘通訊機制不一樣的是,
   它可用於不一樣及其間的進程通訊。
11九、關鍵字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、如何防止同時產生大量的線程,方法是使用線程池,線程池具備能夠同時提升調度效率和
  限制資源使用的好處,線程池中的線程達到最大數時,其餘線程就會排隊等候 
12一、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'了;
12二、操做系統的內存分配通常有哪幾種方式,各有什麼優缺點?
 定長和變長。
 變長:內存時比較靈活,可是易產生內存碎片。
 定長:靈活性差,但分配效率較高,不會產生內存碎片 
12三、全局變量可不能夠定義在可被多個.C文件包含的頭文件中?爲何?
 答:能夠,在不一樣的C文件中以static形式來聲明同名全局變量。能夠在不一樣的C文件中聲明同名的全局變量,
 前提是其中只能有一個C文件中對此變量賦初值,此時鏈接不會出錯 
12四、肯定模塊的功能和模塊的接口是在軟件設計的那個隊段完成的?概要設計階段 
12五、#define N 500
 unsigned char count;
 for(count=0;count < N;count++)
 {
  printf("---%d---\n",count);
 }死循環,由於unsigned char 最大爲255
12六、給定結構struct A 
   {       
    char t:4; 4位       
    char k:4; 4位       
    unsigned short i:8; 8位             
    unsigned long m; // 偏移2字節保證4字節對齊
   }; // 共8字節 
12七、ICMP(ICMP協議對於網絡安全具備極其重要的意義)功能主要有:
 · 偵測遠端主機是否存在。
 · 創建及維護路由資料。
 · 重導資料傳送路徑。
 · 資料流量控制。
 
 
 單向、雙向鏈表操做、寫一個快速排序算法(原理:找一個基準值,分別將大於和小於基準值的數據放到基準值左右兩邊,即一次劃分。因爲處在兩邊的數據也是無序的,因此再用一樣的劃分方法對左右兩邊的序列進行再次劃分,直到劃分元素只剩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;
}
二、快速排序
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);
 }
}
三、//二分擦找
 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;}

相關文章
相關標籤/搜索