C和指針 讀書筆記

第一章:快速開始

1.C語言中註釋代碼用/* 和*/來註釋代碼。但是由於/*和*/不能嵌套,故在需要對一大段代碼註釋的時候,內容代碼不能含有註釋/*,*/。但是可以採用宏命令來完成此功能。

#if  0

   /*需要註釋的大段代碼 */

#endif

2.EOF是一個整數值,故在一個一個接受字符判斷是否結束時,用int變量來存放獲得的字符。否則255對應的字符類型轉換成int型後等於-1.

int ch;

while ((ch = getchar() )!=EOF  && ch!='\n')

第二章:基本概念

1.C語言從編譯到執行的過程,合法標識符,轉義序列,特別注意三字符序列的存在。

第三章:數據

1.C語言中四種基本數據類型:整型,浮點型,指針和聚合類型(struct,array).

2.使用typedef而不是#define來給類型命名別名。如下面列子:

#define ptr_to_char char *

ptr_to_char a, b;   // b is char

typedef char * ptr_char;

ptr_char a,b;       //  both a and b are pointers

3.儘量用const修飾變量:不僅程序邏輯清晰,而且代碼中嘗試修改變量都會報錯。

4.static用於定義函數或全局變量時,會將對應的鏈接屬性從external改爲internal,存儲類型和作用域不變。對應函數和變量只能在聲明他們的源文件中訪問;  static作用於代碼內部變量聲明時,會講變量從局部變量改爲靜態變量。但是變量的鏈接屬性和作用域不受影響。

第四章:語句

1.C語言中沒有bool類型變量(見第三章第1條),用整型變量來代替(0代表false,1代表true)

2.C語言沒有內置輸入輸出功能,I/O通過標準庫函數進行實現。

3.goto唯一可以適合使用的場景是跳出多重循環。

第五章:操作符和表達式

1.注意邏輯移位與算術移位的區別.算術右移位時考慮數的正負號。

2.用移位操作對某個數的某一位操作:

value = value | 1<<bit_num;            //置1

value = value & ~(1<<bit_num);  //清零

value & 1<<bit_num;            //測試是否爲1

第六章:指針

1.對一個NULL指針進行解引用是非法操作。故在對指針進行解引用操作時,要確保指針不是NULL.

2.對指針進行算術運行的前提是兩個指針是指向同一個array,否則結果是undefined.

3.指針指向一個array時,指針可以跟array最後一位的下一位進行比較。但若用指針與array第一位的前一位進行比較,標準未定義即undefined。故要避免此種用法。

3.指針要記得初始化,不用時記得設爲NULL.(remember...)

第七章:函數

1.函數進行參數傳遞時,都是採用傳值的方式。(原先參數的一份拷貝)。在傳遞array參數時,不是講整個參數傳遞,而是傳遞了array的起始地址。

2.尾遞歸可以比較容易的用迭代實現。

第八章:數組

1.除了優先級外,間接引用可以和下標引用互換。

2. message大小爲6.

char * message = "hello";

3.二維數組的傳遞:

int matrix[3][10];
func2(matrix);

void  func2(int (*mat)[10]);
void  func2(int mat[][10]);

4.指針數組的理解:

int *ptr[10];

ptr是指向整型指針的指針,元素是指向整數的指針。

第九章:字符串,字符和字節

1.strlen的原型爲:

size_t strlen(char const * string)

size_t是unsigned int 類型。故 if(strlen(x) >= strlen(y)) 與 if(strlen(x)-strlen(y) >=0) 不同,後者總是爲true.

2.strncat函數一般會講len個字符從src字符串加入到目標字符串,而且strncat總會在末尾加上一個NULL字符。

3.strncpy則總是複製n個字符,若原字符不足n個,則用NULL加到末尾。但是若n個字符最後一個不是NULL,則會出現最後的字符串是非NULL結尾的情形。故使用strncpy函數時,最好按如下方法:

strncpy(buffer, name, size);

buffer[size-1] = '\0';

4.爲了提高程序的可移植性,減少對字符的直接操作。如判斷一個字符是否是大寫字符: if(ch >= 'A' && ch <= 'Z') 改爲 if(isupper(ch))

5.對內存操作的幾個函數:

// 若內存重疊,則結果undefined

void * memcpy(void *dst. void const * src, size_t length);

//與上一個函數類似,可以內存重疊

void *memmove(void *dst, void const *src, size_t lenth);

void *memcmp(void const *a, void const *b, size_t length);

void *memchr(void const *a, int ch, size_t length);

void *memset(void *a, int ch , size_t length);

第十章:結構和聯合

1.Union 與Struct結構類似,只是Unino的所有成員引用的是內存中的相同地址。如果聯合的各個成員具有不同的長度,聯合的長度就是它最長成員的長度。

2.sizeof(struct X)包括任何由於端對其而浪費的內存。

3.free(NULL) is ok.

第十一章:動態內存分配

1.動態內存的分配與釋放:

void *malloc(size_t size);

void free( void *pointer);

2.還有另外兩個內存分配函數realloc和calloc:

void *calloc(size_t num_elements, size_t element_size);
void realloc(void *ptr, size_t new_size);

若ptr爲NULL,則與malloc一樣

第十二章:使用結構和指針

1.在對單鏈表進行操作時,主要對頭結點和尾節點的考慮。

第十三章:高級指針話題

1.函數指針最常見的兩個用途是轉換表和作爲參數傳遞給另一個函數

2.對函數指針執行間接訪問之前必須把它初始化爲指向一個函數:

int  (*pf)(int) = &f;

int ans;

ans = f(25);
ans = (*pf)(25);
ans = pf(25);

第十四章:

1.幾個基本預處理符號:

(1)__FILE__         // 進行編譯的源文件名;

(2)__LINE__        // 文件當前行的行號;

(3)__DATE__        // 文件被編譯的日期;

(4)__TIME__        // 文件被編譯的時間;

(5)__STDC__       //如果編譯器遵循ANSI C,其值爲1,否則未定義;

2.#define宏使用時存在很多潛在的危險,如:

   #define max(x,y)  (  (x>y) ? (x) : (y)  )

第十五章:

1.I/O函數以三種基本的形式處理數據:單個字符、文本行和二進制數據。

2.參考相應的手冊。

第十六章:標準庫函數

1.該部分比較複雜,書上也只是提及了部分的函數。如時間相關函數time,clock.隨機數srand(),rand()。

2.fgets會在字符後加一個NULL.

char *fgets(char *buffer, int buffer_size, FILE * stream);

3.fputs可以輸出一行或者一行的一部分。

3.gets未指定buffer的大小,故接收一行的多字符時會溢出。

char *gets(char *buffer)

發佈了57 篇原創文章 · 獲贊 3 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章