第一章:快速開始
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)