《Linux C編程一站式學習》閱讀筆記(2):

預處理算法

#和##是兩個預處理運算符(注意不是C語言表達式的運算符),#後接形參(中間能夠空格),用於建立字符串字面值;##用於鏈接兩個形參。shell

函數式宏定義也能夠帶可變參數,一樣是用…表示可變參數,宏定義中的可變參數的部分用_VA_ARGS_表示。如:編程

#define  showlist(…)  printf(#_VA_ARGS_)windows

取消宏定義用#undef ,取消未定義的宏不算錯誤。函數

對條件預處理的編譯(#if …  #elseif…  #else…  #endif),可選的方法有:一、手動編輯代碼,添加定義目標宏;二、在全部須要配置的源文件開頭包含一個頭文件,在該頭文件中定義目標宏;三、經過gcc -D選項在編譯時定義目標宏 43。spa

C標準中規定了幾個特殊的宏,不需定義便可使用,最經常使用的是_FILE_ (展開成當前源文件名)和_LINE_(當前代碼行的行號)。命令行

C99標準引入特殊標識符_func_可表示當前函數名,這是一個變量名(字符串變量)而不是宏定義。指針

第21章  Makefile基礎code

make程序自動讀取當前目錄下的Makefile文件(依次查找名爲GNUmakefile、makefile和Makefile,通常建議用Makefile作文件名)。blog

make執行的命令前加了@,則不顯示命令自己而只顯示輸出結果,前加- ,則即便該命令出錯也繼續執行後面的命令。

Makefile中約定俗成的目標名字有:all(執行編譯,一般爲缺省)、install(執行編譯後的安裝工做,把可執行文件、配置文件、文檔等分別複製到不一樣的安裝目錄)、clean(刪除編譯生成的二進制文件)、distclean(不只刪除二進制文件,也刪除其餘的生成文件)。

make中, := 賦值時遇到變量當即展開; ?=  賦值時若是沒定義過,就進行定義並賦值(不當即展開),若是定義過了就什麼也不作;還可以使用+=。

gcc 的 -M選項自動分析目標文件和源文件的依賴關係。

第22章 指針

gcc把字符串字面值分配在.rodata段,因此字符串字面值作右值時最好理解成const char* 類型。

 在gdb中,能夠在run或start命令後面加入命令行參數(從arg[1]開始),也能夠用set args命令設置命令行參數以後用run或start運行程序。

兩層指針若是是傳出的,可能有兩種狀況:一、傳出的指針指向靜態內存,或指向已分配的動態內容;二、在函數中動態分配內存,而後傳出的指針指向這塊內存。

第23章  函數接口

回調函數

若是參數是函數指針,調用者能夠傳遞一個函數的地址給回調函數的實現者,也就是說,調用者提供一個函數但本身不去調用它,而是讓經過使用回調函數,讓回調函數的實現者去調用它。

回調函數能夠實現相似於C++的虛函數或者泛型算法的功能。

處理可變參數要用到C標準庫的va_list類型和va_start、va_arg、va_end宏,它們都定義在stdarg.h頭文件中。從下面的例子可大體看出具體的用法:

#include <stdio.h>
#include <stdarg.h>

 void printlist(int begin,…)
{
      va_list ap;
      char *p;

      va_start(ap,begin);
      p=va_arg(ap,char *);  
      
      while(p!=NULL) {
            fputs(p,stdout);
            putchar('\n');
            p=va_arg(ap, char*);
      }
      va_end(ap);

}
int main(void)
{
      printlist(0,"hello","world","foo","bar",NULL);
      return 0;
}

 

第24章  C標準庫

Linux平臺提供的C標準庫包括:一、一組頭文件,定義了不少類型和宏,聲明瞭不少庫函數和全局變量;二、一組庫文件,提供了庫函數和局變量的定義。

分割字符串:

 char *strtok(char *str, const char *delim);
 char *strtok_r(char *str, const char *delim, char **saveptr);

 strtok會不斷修改str的值,同時在函數中使用一個靜態變量記住處理到字符串的位置,這使得strtok不可重入。而strtok_r不使用靜態變量,而是要求調用者使用一個變量記錄處理位置,並將處理位置傳給strtok_r做爲第三個參數。strtok_r中的r表示Reentrant(可重入的)。Man Page中有一個使用strtok_r的很好的例子,可對分割後的子串再進行分割處理。

windows的換行符是\r\n,Unix的換行符是\n。

fopen原型:FILE *fopen(const char *path,const char *mode);  打開文件出錯,fopen返回NULL並設置errno。

FILE是C標準庫中定義的結構體類型,包含了文件描述符、用戶空間I/O緩衝區和當前讀寫位置等信息。像FILE *這樣的指針稱爲不透明指針(Opaque Pointer)或句柄(Handle)。

fclose原型:int fclose(FILE *fp); fclose調用出錯返回EOF並設置errno。

使用ls命令查看設備文件時,在普通文件顯示文件大小的地方顯示的是設備號(如5,0),其中主設備號5標識內核中一個設備驅動程序,次設備號標識該設備驅動程序管理的一個設備。

終端設備在shell進程啓動時自動打開,並用三個FILE *指針stdin、stdout和stderr指向設備,這三個指針是libc中定義的全局變量,在stdio.h中聲明,printf向stdout寫,而scanf從stdin讀。

fgetc函數從指定文件中讀一個字節,getchar從標準輸入中讀一個字節,調用getchar()至關於調用fgetc(stdin)。fgetc返回值爲int型(讀取unsigned char要轉換爲int),由於它出錯會返回EOF(0xffffffff),若是返回值爲unsigned char型則沒法區分是EOF仍是字節0xff。相對應的有fputc和putchar。

操做讀寫位置的函數fseek、ftell、rewind。原型以下:

int fseek(FILE *stream, long offset, int whence);  //其中whence參數含義以下:SEEK_SET從開頭移動offset個字節; SEEK_CUR從當前; SEEK_END從末尾。  

long ftell( FILE *stream);  //返回當前讀寫位置

void rewind(FILE *stream); //移動到文件開頭

gets不能指定緩衝區大小,在編程時不該當使用。

函數printf、scanf有多種形式,其中以v開頭表示可變參數不是以…的形式傳進來,而是以va_list類型傳進來。

使用scanf函數時要注意c%是能夠匹配空白字符的,匹配時不會跳過,要想跳過開頭的空白字符,能夠在格式化字符串的c%前面用一個空格去匹配。

I/O緩衝區、flush、exit。

相關文章
相關標籤/搜索