c專家程式設計

2021-06-21 21:15:02 字數 4833 閱讀 2583

------------------------------pag13 

關於替代庫函式

標準規定編譯器只有在違反語法規則約束條件的情況下才能產生錯誤資訊。

所有c語言標準標頭檔案中宣告的識別符號均保留,所以不能宣告乙個叫做malloc()的函式,因為在標準標頭檔案裡已經有乙個函式以此為名。但由於這個規定不是約束條件,因此可以違反他。(所以可以用自己宣告的函式來替換標準標頭檔案,如:串列埠通訊putchar替換)

------------------------------pag19 (關於const修飾指標

每個實參都應該具有自己的型別,這樣他的值就可以賦值給他所對應的形參型別的物件(該物件的型別不能含有限定符)。

要使上面賦值合法,必須滿足下列條件之一:

兩個運算元都是指向有限定符或無限定符的相容型別的指標,左邊指標所指向的型別必須具有右邊指標所指向型別的全部限定符。

char 

*cp;

const 

char 

*ccp;

ccp = cp;

上例是可以的,因為char與char相容,且左運算元具有右運算元限定符(無),再加上自身限定符。

char 

**cp;

const 

char 

**ccp;

ccp = cp;

上例是不行的,因為:

cp -》 (char*) 

-》char

ccp-》(const char*) -》 const char 

括號是乙個整體的意思,沒有分離出來的限定符!)

cp指向的是字元指標,ccp指向的是常字元指標,兩者指向物件不同,(這裡和上例不一樣,因為char和const char是有無限定符的問題,而(char *)和(const char*)已經分別是乙個整體了(都是指標,無限定符),所以不存在有無限定符問題,是型別不一樣!)所以不相容。雖然他們的最終指向char和char相容,但是相容無法傳遞。

總之為了防止誤用,應盡量避免用含有const修飾兩層深度以上的指標。

------------------------------pag23 (型別轉換

資料型別一般朝著浮點精度更高,長度更長的方向轉換,整形數如果轉換為signed不會丟失資訊,就轉換為signed,否則轉換為unsigned。

------------------------------pag 24 (有符號數和無符號數

有符號數和無符號數是無法進行直接相比的,因為有符號數會被提公升為無符號數,可能產生錯誤結果。(sizeof返回的是無符號數)

------------------------------pag28 (『\0』字元佔空間

無論在什麼時候,如果遇見了這樣一條語句malloc(strlen(str));,幾乎可以肯定他時錯誤的,而malloc(strlen(str) + 1);才是正確的,因為其他字串處理庫函式幾乎都包含乙個額外空間,用於容納字串結尾的'\0'字元。strlen是個特殊情況,他不將'\0'計入。

乙個'l'的nul用於結束乙個ascll字串。

兩個'l'的null用於表示什麼也不指向(空指標)。

------------------------------pag31 (const不是常量

const關鍵字並不真正表示常量。(在case和陣列宣告中可以體現出來,編譯無法通過)

------------------------------pag39 (運算子優先順序

算術運算子高於移位運算子:msb《4+lsb和msb《(4+lsb)等價!(我過去犯過,百思不得其解)

逗號運算子在所有運算子中優先順序最低。

------------------------------pag41 (結合性

結合性只用於表示式中出現兩個以上相同優先順序的操作符的情況。所有優先順序相同的操作符,他們的結合性也相同。

------------------------------pag59 (c語言宣告限制

非法:

合法:pag60 (段位

struct pid_tag

unsigned int inactive : 1;

unsigned int 

: 1;  (乙個位的填充)

unsigned int refcount : 6;

unsigned int 

: 0; (填充到下一字邊界)

short pid_id;

struct pid_tag *link;

位段的型別必須是,int,unsigned int, signed int(或加上限定符)。

------------------------------pag61 (引數傳遞

引數傳遞首先盡可能地存放在暫存器中,不夠了再存在堆疊中。

乙個int型引數一般會被傳遞到暫存器中,而結構引數則很可能被傳遞到堆疊中。

------------------------------pag62 (聯合

union bits32_tag

int whole;

struct byte;

}  value;

這個聯合允許程式設計師提取整個32位值(作為int),也可以提取單獨的位元組段如value.byte.c0。

------------------------------pag64 (c宣告優先順序

a  宣告從他的名字開始讀取,然後按照優先順序順序依次讀取。

b  優先順序從高到低依次是:

b1 宣告中被括號括起來的那部分

b2 字尾操作符:

括號()表示這個乙個函式,而放括號表示這是乙個陣列

b3 字首操作符:星號*表示「指向。。。的指標」

c  如果const和volatile關鍵字的後面緊跟著型別說明符(如int,long等),他作用於型別說明符。在在其他情況下,const和volatile關鍵字作用域他左邊緊鄰的指標星號。

例:char * const *(* next)();

a  首先,看變數名「next」,並注意到他直接被括號所括住

b1  所以先把括號裡的東西作為乙個整體,得出「next是乙個指向...的指標」

b  然後考慮括號外面的東西,在星號字首和括號字尾之間作出選擇

b2  b2規則告訴我們優先順序較高的是右邊的函式括號,所以得出「next是乙個函式指標,指向乙個返回...的函式」

b3  然後,處理字首「*」,得出指標所指的內容

c  最後,把「char *const」解釋為指向字元的常量指標

結果:next是乙個指標,他指向乙個函式,該函式返回另乙個指標,該指標指向乙個型別為char的常量指標。

------------------------------pag68 (typedef和#define

1、可以用其他型別說明符對巨集型別名進行擴充套件,但對typedef所定義的型別名卻不能這樣做

#define peach int

unsigned peach i; //合法

typedef int banana;

unsigned banana i;//非法

2、在連續幾個變數的宣告中,用typedef定義的型別能夠保證宣告中所有變數為同一型別,#define只有第乙個

------------------------------pag71(typedef應該用在:

1、陣列、結構、指標以及函式的組合型別

2、可移植型別。如 typedef unsigned int int16_t;移植時只要在typedef中修改就可以

------------------------------pag83(宣告陣列時的長度

由於並未在宣告中為陣列分配記憶體,所以並不需要提供關於陣列長度的資訊。對於多維陣列,需要提供最左邊一維之外其他維的長度---這就給編譯器足夠的資訊產生相應的**。

------------------------------pag85(陣列指標差異

extern char *p;

p[3];

編譯器:

1、取得符號表(.symtab)(存放定義和引用的函式和全域性變數資訊)中指標p的位址,提取儲存於此處的值(位址)

2、把下標表示的偏移量與位址值相加,產生另乙個位址

3、訪問上面這個位址,取得字元

之所以會如此,是因為我們告訴編譯器我們擁有的是乙個指標。

但是只有當p原來定義為指標時這個方法才是正確的。

檔案a.c

char p[10];  (p中是字元)

檔案b.c

extern char *p; (p中是位址)

p[i];

當用p[i]這種形式提取這個宣告的內容時,實際上得到的是乙個字元。但編譯器按照上面的3個步驟,卻把他當成是乙個指標!

加上點我自己的理解:

第二個例子和常見的函式中實參傳遞給形參的拷貝值並不一樣,上面這樣相當於把*p和p[10]等同了,類似給檔案a.c中的陣列p加上了這樣乙個操作:(char *)p[0~9]。像上面第二中情況,因為編譯器在編譯階段已經確認了p的型別,於是後面無法改變,鏈結時就出現了相應的問題。如果在像char *p = "abcd";p[3];這樣出現在同一檔案中,編譯器編譯時就知道p是乙個指標,並按照指標的方式處理,不會把p當成陣列名那樣看成指標常量(就是位址值)直接加上3個元素的大小,然後取位址中的值,而是提取指標變數p中的值作為位址做相應操作。定義為指標時要比定義為陣列時多一層提取!

所以跨檔案時不要這樣做,陣列就宣告成陣列,指標就宣告成指標!

C專家程式設計

說到c語言,首稱 c程式語言 這是一本入門和進修均可的書籍,值得讀三遍以上,方才有味。進修書籍如 c專家程式設計 是一本c語言較高層次的書,是成為c語言專家的必經之路。我自以為達到了一定的 程度,才開始學習這本書的。人言,c語言是一門藝術,需要多年歷練才能達到較為完善的境界,此言不虛。c語言進修書籍...

C 專家程式設計

2011.9.4 c 專家程式設計 1 容易混淆的 const 關鍵字const 並不能把乙個變數變為常量,它修飾的符號僅表示該符號的值不能被賦值,也就意味著唯讀不可寫,但它並不能防止通過程式內部 甚至外部,其它函式 的方法來修改它。const 最有用支出是用來限定函式的形參,這樣該函式不會修改實參...

c專家程式設計

近來,看了一下 c專家程式設計 這本書,還是有一點收穫吧!也許,我的水平還不適合讀這本書吧!但是,將書中的一些注意點記在這兒。1.要使二個賦值形式合法,必須滿足一下條件 二個運算元都是指向有限定符或者無限定符的相容型別指標,左邊指標所指向的型別必須具有右邊指標指向型別的全部限定符。比如 char c...