2017年1月15日 11:20:59雜項

位操做面試

位操做的必要性:經過串口或並口與其餘器件相連函數

&按位與優化

|按位或spa

^按位異或:兩位相異時爲1,相同時爲0.日誌

上述三個操做知足結合律和交換率。遞歸

 

左移運算符:<<將要運算的二進制位左移編譯器

規則:高位丟棄,低位補0.數學

使用格式:io

int a = 1<<1;編譯

a = 2;

右移運算符:>>講要運算的二進制右移

規則:高位補符號位,地位丟棄。

符號位:若爲正數則符號位是0,負數符號位爲1

 

小技巧:

左移n位至關於乘以2n次方,但效率比數學運算高。

右移n位至關於除以2n次方,但效率比數學運算高。

 

 

防錯準則:

避免位操做運算符,邏輯運算符和數學運算符同出如今一個表達式中

當位運算符,邏輯運算符和數學運算符須要同時參與運算時,儘可能使用括號()來表達計算次序。

嵌入式比較講究效率!

 

加減法的優先級高於左移和右移。

 

交換兩個變量:利用#define\代碼塊替換

 

#define SWAP1(a,b) \

{   \

int temp = a; \

a = b; \

b = temp; \

} \

 

#define SWAP2(a,b) \

{   \

a = a + b; \

b = a - b ; \

a = a - b ; \

} \

問題:若是a很大,b很大,a+b的值可能會使a溢出。

 

#define SWAP3(a,b) \

{   \

a = a ^ b; \

b = a ^ b ; \

a = a ^ b ; \

} \

 

位運算符的效率比加減高得多,整數交換建議用第三種方法。

 

 

 

 

某個面試題:

有一個數列,其中的天然數都是以偶數的形式存在,只有一個天然數出現的次數爲奇數次,找出這個數。

 

貪心法——++--表達式閱讀技巧

1.編譯器處理的每一個符號應該儘量多的包含字符

2.編譯器從左像右一個一個儘量多的讀入字符

3.立即將讀入的字符不可能和已讀入的字符組成合法符號爲止。

 

 

程序編譯的四個步驟:

.c.h文件通過預處理cpp產生.i文件,再通過編譯器gcc,產生.s文件,通過彙編器as產生.o文件,.o.a文件通過連接器產生.out文件。

 

預編譯階段:

處理掉全部註釋,用空格代替。

#define刪除,展開全部的宏

處理條件編譯指令#if,#ifdef,#elif,#else,#endif.

處理#include,展開被包含的文件

保留編譯器須要使用的#pragma指令

預處理指令:gcc-E file.c-o hello.i

 

編譯階段:

對預處理文件進行一系列的詞法分析,語法分析和語義分析

詞法分析:關鍵字,標示符,當即數等

語法分析:表達式是否遵循語法會澤

語義分析:在語法分析的基礎上進一步分析

生成.i文件

 

分析結束後,進行代碼優化生成相應的彙編代碼文件

編譯指令: gcc-S file.c -o hello.s

生成.s文件。

 

連接器:將.o文件和庫文件裝載在一塊兒,生成最終可執行文件。

 

與源代碼密切相關的,預處理,編譯,彙編。

 

連接器

做用:把各個模塊之間相互引用的部分處理好,使個個模塊正確銜接。

 

#define定義宏常量能夠出如今代碼的任何地方

#define從本行開始,以後的代碼均可以使用這個宏常量。

#define 別名 原內容

#define 路徑用法:

#define  PATH_1  D:\XYZ\test.c

 

#define表達式有函數調用的假象,卻不是

#define表達式能夠比函數更強大

#define表達式比函數更容易出錯

 

 

printf(「%d\n」,((i++<j)  ? (i++)  :  (j)));

 

 

宏表達式在預編譯期被處理,編譯器不知道宏表達式的存在

宏表達式用「實參」徹底替代形參,不進行任何計算。

宏表達式沒有任何「調用」開銷

宏表達式不能出現遞歸定義

 

宏定義的範圍

#define   X    256

//如下可以使用,直到#undef X

#undef   X

 

強大的內置宏

含義 示例

_FILE_   被編譯的文件名 file1.c

_LINE_ 當前行數 25

_DATE_ 編譯時日期 Jan312012

_TIME_ 編譯時時間 170101

_STDC_ 是否遵循標準C規範 1

 

 

 

定義日誌宏

若是用函數來寫日誌:

void log(char* s)

{

printf(「%s %d %s\n」,_FILE_,_LINE_,s); //

}

 

若是在文件中不停調用這個函數,會發現顯示的第二個數據一直爲函數定義時的行數。

由於要調用這個函數時,須要跳回函數執行,這樣只會輸出定義函數時的行數。

這時須要用到宏定義

 

#define LOG(s) \printf(「%s %d %s\n」,_FILE_,_LINE_,s);

 

這幾個信息不夠,還須要加上時間

先包含時間頭文件,#include 「time.h」

void f()

{

time_t t;

struct tm* ti;

time(&t);

ti = localtiome(&t);

printf(「%s %d %s」,asctime(ti),_LINE_,_FILE_,s);

}

如何將這個函數加到宏定義

 

#define LOG(s)  do{ \

time_t t; \

struct tm* ti; \

time(&t); \

ti = localtime(&t); \

printf(「%s [%s %d],%s」,asctime(ti),_FILE_,_LINE_,s); \

}while(0);

牛叉的續行符!

 

課後思考:

#define  f   (x)      ((x)-1)

宏表明什麼意思?對空格敏感麼?宏「調用」對空格敏感麼

相關文章
相關標籤/搜索