1. 程式人生 > >C語言---總結

C語言---總結

基礎

  • 程式結構是三種: 順序結構、選擇結構(分支結構)、迴圈結構。
  • 讀程式都要從 main()入口, 然後從最上面順序往下讀(碰到迴圈做迴圈,碰到選擇做選擇),有且只有一個main函式。
  • 計算機的資料在電腦中儲存是以二進位制的形式. 資料存放的位置就是他的地址.
  • bit是位,指為0或1。byte是指位元組,一個位元組=八個位。
  • 每個C語言程式寫完後,都是先編譯,後連結,最後執行。(.c→.obj→.exe)這個過程中注意.c 和.obj 檔案時無法執行的,只有.exe檔案才可以執行。

常考

  • 編譯預處理不是 C語言的一部分,不佔執行時間,不要加分號。
    C語言編譯的程式稱為源程式,它以ASCII數值存放在文字檔案中。
  • define PI 3.1415926; 這個寫法是錯誤的,一定不能出現分號。
  • 每個C語言程式中main函式是有且只有一個。
  • 在函式中不可以再定義函式。
  • 演算法:可以沒有輸入,但是一定要有輸出。
  • break可用於迴圈結構和switch語句。
  • 逗號運算子的級別最低,賦值的級別倒數第二。
  • int *p 中 *p 和 p 的差別:簡單說*p 是數值,p 是地址!
    • *p:可以當做變數來用;*的作用是取後面地址 p 裡面的數值。
    • p:是當作地址來用。可以用在 scanf 函式中:scanf(“%d”,p);
  • *p++ 和 (*p)++的之間的差別:(筆試重點)
    • *p++:是地址會變化。
      口訣:取當前值,然後再移動地址!
    • (*p)++:是數值會要變化。
      口訣:取當前值,然後再使數值增加 1。

      例題:int *p,a[]={1,3,5,7,9};
      p=a;
      請問*p++和(*p)++的數值分別為多少?
      *p++:這個本身的數值為1。由於是地址會增加一,所以指標指向數值3了。
      (*p)++:這個本身的數值為1。由於++表示數值會增加,指標不移動,但數值1由於自加了一次變成了2。

  • 二級指標:
    • *p:一級指標:存放變數的地址。
    • **q:二級指標:存放一級指標的地址。

      常考題目:int x=7;int*p=&x,**q=p;
      問你:*p 為多少?*q為多少?**q為多少?
      *p=7,*q=p,**q=7

      再問:**q=&x 的寫法可以嗎?不可以,二級指標只能存放一級指標的地址。

  • 程式進行編譯時,並不為形式引數分配儲存穿間。只有在被呼叫時,形式引數才臨時地佔有儲存空間。形式引數用關鍵字auto作儲存類別的宣告時,關鍵字“auto”可以省略,auto 不寫則隱含確定為“自動儲存類別”,它屬於動態儲存方式。
  • 函式的儲存型別是函式定義時函式名前面的資料型別前面的儲存型別,預設時應該是:extern,表示該函式屬外部函式(即 可以被本 C 檔案外的其他 C 源程式檔案中的函式呼叫)
    • extern:
      對整個工程可見,其他檔案可以使用extern外部聲明後直接使用。也就是說其他檔案不能再定義一個與其相同名字的變量了(否則編譯器會認為它們是同一個變數)
    • static:代表靜態全域性
      僅對當前檔案可見,其他檔案不可訪問,其他檔案可以定義與其同名的變數,兩者互不影響。

重點

  • strlen 和 sizeof 的區別(重點):
    • sizeof:(求實際儲存空間)
      相當於是個巨集一樣的東西,因為它只是一個運算子,而不是函式,編譯時展開為常數,編譯的時候有每個變數的定義表,sizeof通過查表確定變數佔用的空間,這是分配記憶體給process 之前要確定的。
      其實可以簡單的理解sizeof是針對"型別"的,而非"變數",但此時不能這樣看如:sizeof("HELLO");中括號中為const char *,而是一個"字串",所以結果大小為 5.但:
    char *ps = "HELLO";
    sizeof(ps) = 4  //只是指標的大小,即 地址(整數型別佔4個位元組)
    sizeof(*ps) = 1 //*ps+0代表陣列第一個元素的大小,即ps[0]
    
    char as[8];
    sizeof(as) = 8  //因為as的型別為 char [8],這個大小的確是8
    sizeof(*as) = 1 //*as+0代表陣列第一個元素的大小,即as[0]
    
    char aa[8][9];
    sizeof((char *)aa) = 4  //還是 char *
    
    char arr[100] = "HELLO";
    sizeof(arr) = 100   //和賦什麼值沒什麼關係,關鍵是"型別"是什麼
    
    int func(char p[100]) {
        sizeof(p) = 4;
        /*C/C++中不能傳陣列,只能傳指標,所以任何陣列都會隱式轉成指標形式進行操作。*/
    }
    • strlen:(求字串長度,即 字元個數,不包括結束符)
      它是一個函式,引數是 const char*,搞清楚它的實現,就是碰到‘\0‘(字串結尾,就停止計數,但不包括‘\0‘)。所以它不是看型別而是看變數,取決於變數賦的什麼值。
  • 函式的遞迴一定會考。
  • 兩種重要的陣列長度:
    char a[]={‘a’,’b’,’c’}; 陣列長度為3,字串長度不定(因為沒有'\0'結束符)。sizeof(a)為3。
    char a[5]={ ‘a’,’b’,’c’}; 陣列長度為5,字串長度3。sizeof(a)為5。
    char a[]={'a','b','c'}; 這是一個字元陣列,佔3個位元組。
    char a[]="abc" 則不同,它是一個字串,最後還有一個'\0'結束符,佔4個位元組。

  • scanf 和 gets 的區別:
    如果輸入的是 good good study!
    • scanf(“%s”,a);
      只會接收 good。 考點:不可以接收空格。(遇到空格或回車就終止)
    • gets(a);
      會接收 good good study! 考點:可以接收空格。(遇到回車終止)
  • 指標考點:
    char ch[]=”iamhandsome”;
    char *p=ch;
    問你:*(p+2) 和 *p+2 的結果是多少?
    *(p+2) = ‘m’ *p+2 = ‘k’

    解析:
    第一個是地址+2,所以取m;
    第二個則是數值+2,即 ASCII碼值+2,ijk,所以取k。

  • 字串的賦值:
    C語言中沒有字串變數,所以用陣列和指標存放字串:
    1. char ch[10]={“abcdefgh”}; 對
    2. char ch[10]=“abcdefgh”; 對
    3. char ch[10]={‘a’,’b’,’c’,’d’,’e’,’f’,’g’,’h’}; 對
    4. char *p=“abcdefgh”; 對
    5. char *p; 對
    6. ch=“abcdefgh”; 錯!陣列名不可以賦值!(只能一個一個迴圈賦值)
    7. char *p={“abcdefgh”}; 錯!不能夠出現大括號!
  • 逗號表示式:
    優先級別最低。表示式的數值逗號最右邊的那個表示式的數值。
    (2,3,4)的表示式的數值就是4。
    z =(2,3,4)(整個是賦值表示式),這個時候z的值為4。
    z = 2,3,4 (整個是逗號表示式),這個時候z的值為2。

巨集定義defind

問題:#define f(x)(x*x) 和 #define f(x) x*x 之間的差別。

define是C語言中的巨集定義關鍵字,其定義格式如下:

#define [MacroName] [MacroValue]巨集定義分為普通巨集定義和帶引數的巨集定義

  • 普通巨集定義:#define PI (3.1415926)

  • 帶引數的巨集定義 (巨集函式):#define max(a,b) ((a)>(b)? (a),(b))
    注意:變數在巨集中要用括號括起來。
    因為,在C語言中define巨集定義在編譯時,會被展開,進行“傻瓜式”替換,也稱為“字面”替換,如果沒有括號有可能會產生歧義。

    如:

    int a,b,c,d,e;
    a=1;b=2;c=6;d=4;
    e=f(a+b) * f(c+d) ;  //理論值e=9*100=900
    
    #define f(x)(x*x)
    替換結果為:e=(a+b*a+b)*(c+d*c+d) = 5*34=170
    
    #define f(x) x*x 
    替換結果為:e=a+b*a+b*c+d*c+d=1+2+12+24+4=43
    
    #define f(x) ((x)*(x))
    替換結果為:e=( (a+b)*(a+b)*(c+d)*(c+d) )=3*3*10*10=900

    這個才是我們想要的結果!

字元

  • 字元資料的合法形式:
    '1' 是字元佔一個位元組,"1"是字串佔兩個位元組(含有一個結束符號)。
    '0' 的 ASCII 數值表示為 48,'a' 的 ASCII 數值是 97,'A'的 ASCII 數值是 65。
    一般表示單個字元錯誤的形式:'65' "1"
    字元是可以進行算術運算的,記住:'0'-0=48

  • 大寫字母和小寫字母轉換的方法:
    'A'+32='a' 相互之間一般是相差32。
    這個32不用記,要用的時候直接'a'-'A',就可以得出轉換大小寫的數值了。

  • 字元型和整數是近親:兩個具有很大的相似之處
    char a = 65 ;
    printf(“%c”, a); 得到的輸出結果:a
    printf(“%d”, A); 得到的輸出結果:65

轉義字元

轉義字元分為一般轉義字元、八進位制轉義字元、十六進位制轉義字元。

  • 一般轉義字元:背誦\0、 \n、 \’、 \”、 \\。
  • 八進位制轉義字元'':‘\141’ 是合法的, 前導的0是不能寫的。
  • 十六進位制轉義字元'\x':’\x6d’ 才是合法的,前導的0不能寫,並且x是小寫。

未完待續