天天看點

c語言基礎知識要點

C語言程式的構成

與C++、Java相比,C語言其實很簡單,但卻非常重要。因為它是C++、Java的基礎。不把C語言基礎打紮實,很難成為程式員高手。

一、C語言的結構

先通過一個簡單的例子,把C語言的基礎打牢。

/* clang01_1.c */
         #include                 <stdio.h>

         int                 main(         void                )
{
    printf("這是勸學網的C語言教程。\n");

             return                 0;
}
      

C語言的結構要掌握以下幾點:

  1. C語言的注釋是/* ··· */,而不是//···,//是C++的單行注釋,有的C語言版本也認可。
  2. C語言區分大小寫,每句以分号結尾。
  3. C語言程式是從main函數開始的。函數的傳回值如果預設則為int,而不是void。
  4. 函數必須用return來傳回。即使void類型也不建議省略。
  5. 使用函數時須包含相應的頭檔案。自定義的頭檔案用雙引号,C語言自身的頭檔案用<···>

二、main()函數的寫法與含義

main()的參數和傳回值全部省略,這和上例含義相同。省略寫法是一種很不好的習慣。

main()                                int                 main(         void                )
{                            {
    ···       等同于          ···
}                            }
          

main()的參數是一種不限個數的寫法,argc代表參數的個數,真正的參數是放在argv[]數組裡面的。注意:當數組當參數用時,數組被降格為指針。初學者先照着樣子寫,以後小雅會詳細說明指針和數組的差別。

int                 main(         int                 argc,          char                 *argv[])                            int                 main(         int                 argc,          char                 **argv)
{                                                  {
    ···                       也可寫成              ···
}                                                  }
          

三、頭檔案的意義

每個C程式通常分為兩個檔案。一個檔案用于儲存程式的聲明(declaration),稱為頭檔案。另一個檔案用于儲存程式的實作(implementation),稱為定義(definition)檔案。 C程式的頭檔案以“.h”為字尾,C 程式的定義檔案以“.c”為字尾。

頭檔案的内容也可以直接寫C程式中,但這是很不好的習慣。許多初學者用了頭檔案,卻不明其理。在此略作說明。

  1. 通過頭檔案來調用庫功能。在很多場合,源代碼不便(或不準)向使用者公布,隻要向使用者提供頭檔案和二進制的庫即可。使用者隻需要按照頭檔案中的接口聲明來調用庫功 能,而不必關心接口怎麼實作的。編譯器會從庫中提取相應的代碼。
  2. 頭檔案能加強類型安全檢查。如果某個接口被實作或被使用時,其方式與頭檔案中 的聲明不一緻,編譯器就會指出錯誤,這一簡單的規則能大大減輕程式員調試、改錯的 負擔。

關于頭檔案的内容,初學者還必須注意。

  1. 頭檔案中可以和C程式一樣引用其它頭檔案,可以寫預處理塊,但不能寫語句指令。
  2. 可以申明函數,但不可以定義函數。
  3. 可以申明常量,但不可以定義變量。
  4. 可以“定義”一個宏函數。注意:宏函數很象函數,但卻不是函數。其實還是一個申明。
  5. 結構的定義、自定義資料類型一般也放在頭檔案中。
  6. #include <filename.h>,編譯系統會到C語言固定目錄去引用。#include "filename.h",系統一般首先在目前目錄查找,然後再去環境指定目錄查找。

四、好的風格是成功的關鍵

版本申明、函數功能說明、注釋等是C語言程式的一部分。不養成很好的習慣則不能成為C語言高手(專業人員)。

由于以上部分都是容易忽略的知識點,勸學網上有就直接轉了。轉自勸學網http://www.quanxue.cn/JC_CLanguage/CLang/CLang01.html

二、比較、邏輯、位運算符

隻有類型相同(或C語言能自動轉換)的表達式才能比較,如果類型不同就必須用函數轉換。例如:判斷一字元串的長度是否等于10,就要用strlen()将字元串的長度求出來變成了整型,才能和10比較。

比較運算符隻有6個,即:等于(==)、不等于(!=)、大于(>)、小于(<)、大于等于(>=)、小于等于(<=)。比較運算符也叫關系運算符。

邏輯運算符隻有3個,即:與AND(&&)、或OR(||)、非NOT(!)。

位運算符隻有6個,即:與AND(&)、或OR(|)、非NOT(~)、異或XOR(^)、左移ShiftLeft(<<)、右移ShiftRight(>>)。

三、數組

  1. 數組名也是一變量名,定義時須指定類型和長度。
  2. 長度可以方括号中直接指定,也可以通過指派來間接指定。
  3. 數組可以在定義時直接指派,也可以定義時不指派,之後再指派。
  4. 當使用超出範圍的值時,編譯不出錯,但運作會出錯。(上例運作時出錯後,選“忽略”後得到的結果)

數組的位址

弄清數組位址對使用數組有很大好處,另外,有的函數的參數是指針(如scanf函數),如果要用數組的某一進制素作參數,就必須知道其位址。

#include                 <stdio.h>

         int                 main(         void                )
{

             int                  i;
             int                  iArr[7];
             char                 cArr[] = {\'Q\',\'U\',\'A\',\'N\',\'X\',\'U\',\'E\'};

    //輸出iArr數組和cArr數組的位址
    printf("iArr=%p, cArr=%p\n\n", iArr, cArr);

    //輸出iArr[i]數組和cArr[i]數組的位址
             for                 (i=0; i<7; i++) {
        printf("iArr[%d]=%p, cArr[%d]=%p\n", i, &iArr[i], i, &cArr[i]);
    }

             return                 0;
}      
  1. 數組iArr是int類型,是以它的位址是按4位元組遞增。
  2. 數組cArr是char類型,是以它的位址是按1位元組遞增。
  3. 數組元素的位址是通過數組元素前面加“&”來取得。(如:&iArr[3])
  4. 數組名單獨使用時,代表該數組的首位址。(iArr等同于&iArr[0])(注意:以後使用指針會經常用到這一點)

四、字元數組和字元串的重定義

字元數組就是字元串嗎?有人說是,因為書上這麼寫,教師也這麼教的。小雅不敢說書上或教師們錯了,但至少可以說許多初學者都混淆了這兩個概念。是以,在這此将這2個概念再明确一下。

  1. 字元數組,完整地說叫字元類型的數組。字元數組不一定是字元串。
  2. 字元串是最後一個字元為NULL字元的字元數組。字元串一定是字元數組。
  3. 字元數組的長度是固定的,其中的任何一個字元都可以為NULL字元。
  4. 字元串隻能以NULL結尾,其後的字元便不屬于該字元串。
  5. strlen()等字元串函數對字元串完全适用,對不是字元串的字元數組不适用。
#include                 <stdio.h>
         #include                 <string.h>

         int                 main(         void                )
{
    //這是字元數組賦初值的方法
             char                 cArr[] = {\'Q\',\'U\',\'A\',\'N\',\'X\',\'U\',\'E\'};
    //這是字元串賦初值的方法
             char                 sArr[] ="quanxue";

    //用sizeof()求長度
    printf("cArr的長度=%d\n",          sizeof                (cArr));   //長度為7
    printf("sArr的長度=%d\n",          sizeof                (sArr));   //長度為8,最後一位是NULL

    //用printf的%s列印内容
    printf("cArr的内容=%s\n", cArr);   //不能正确顯示
    printf("sArr的内容=%s\n", sArr);   //可以正确顯示

    //用strlen()求長度
    printf("cArr的長度=%d\n", strlen(cArr));   //不正确的結果
    printf("sArr的長度=%d\n", strlen(sArr));   //NULL不在計算範圍

             return                 0;
}      

從上面例子看來,還要注意以下幾點:

  1. char sArr[] = "quanxue";這種方式,編譯時會自動在末尾增加一個NULL字元。
  2. NULL字元也就是\'\0\',在ASCII表中排在第一個,用16進制表示為0x00。
  3. sizeof()運算符求的是字元數組的長度,而不是字元串長度。
  4. strlen()函數求的是字元串長度,而不是字元數組。它不适用于字元串以外的類型。
  5. char sArr[] = "quanxue";也可以寫成char sArr[8] = "quanxue";(注意:是8而不是7)

字元數組和字元串數組的轉化

字元數組中插入一個NULL字元,NULL字元前面(包括NULL字元)就成了字元串,一般NULL字元插在有效字元的最後。

#include                 <stdio.h>
         #include                 <string.h>

         int                 main(         void                )
{
    //因為最後有NULL,是以這就變成了字元串
             char                 cArr[] = {\'Q\', \'U\', \'A\', \'N\', \'X\', \'U\', \'E\', \'\0\'};
    //因為少定義了一位,最後無NULL,是以這就變成了字元數組
             char                 sArr[7] ="quanxue";
    //最後一個元素未指派
             char                 tArr[16] ="www.quanxue.cn";

    //用sizeof()求長度
    printf("cArr: %2d ,%2d\n", strlen(cArr),          sizeof                (cArr));
    printf("sArr: %2d ,%2d\n", strlen(sArr),          sizeof                (sArr));
    printf("tArr: %2d ,%2d\n", strlen(tArr),          sizeof                (tArr));

    //将tArr的最後一個元素指派,字元串就成了字元數組
    tArr[15] = \'!\';

    //作為字元數組,将顯示16個字元
             for                 (i=0; i<16; i++) printf("%c", tArr[i]);  //字元數組的顯示方法
    //作為字元串,将顯示14個字元。
    printf("\n%s\n", tArr);     //字元串的顯示方法

             return                 0;
}      

數組的輸入輸出『gets(),puts()』

getchar()和putchar()函數是單個字元的輸入輸出,gets()和puts()是字元串的輸入輸出,也是标準函數,在stdio.h中被定義。

五、指針

指針符号『*』和位址符号『&』

『&』符号是取變量的位址,『*』符号是取位址的内容(即:值)。兩個操作正好相反。例如:“&i”就是取變量i的位址,“*(&i)”就是取“&i”這個位址的值,其實就是變量i。即然如此,為什麼還要定義指針呢?原來,用『&』所取到的位址,自身隻能用而不能修改。是以,直接把『&』取到的位址放到指針變量中去,既然指針變量也是變量,這個變量就可以任意存放其它位址。

#include                 <stdio.h>

         int                 main(         void                )
{
             int                 i = 100, j=200;
             int                 *p;

    p = &i;     //變量i的位址賦給p
    printf("&i=%p   *(&i)=%d\n",  &i, *(&i));
    printf(" p=%p   *p   =%d\n\n", p,  *p);

    p = &j;     //變量j的位址賦給p
    printf("&j=%p   *(&j)=%d\n", &j, *(&j));
    printf(" p=%p   *p   =%d\n", p,  *p);

             return                 0;
}      

指針變量的指派和指針的指派

上例中p是指針變量,*p是p的指針,p存放的是某個變量的位址,*p存放的是某個變量的值。當*p的内容改變時,p所指的變量的内容也發生改變,因為是同一個位址的存貯單元的值發生改變。同理,當p所指的變量的值發生改變時,*p的内容也随之改變。

#include                 <stdio.h>

         int                 main(         void                )
{
             int                 i = 100, j=200;
             int                 *p;

    p = &i;     //變量i的位址賦給p
    *p = 500;   //将500賦給p指針
    //變量i的内容也随之改變為500
    printf("&i=%p   *(&i)=%d\n",  &i, *(&i));
    printf(" p=%p   *p   =%d\n\n", p,  *p);

    p = &j;     //變量j的位址賦給p
    j++;        //将p指針的内容+1
    //指針*p的内容也随之改變201
    printf("&j=%p   *(&j)=%d\n", &j, *(&j));
    printf(" p=%p   *p   =%d\n", p,  *p);

             return                 0;
}      

被初始化的是指針變量還是指針

上面2例,指針變量都是用的p,初學者不要認為隻能用p,既然是變量,隻要不違反命名規則都可以。當指針變量被定義時立即指派,這時被指派的是指針變量還是指針呢?下面這段程式請大家千萬注意!

#include                 <stdio.h>

         int                 main(         void                )
{

             char                 str[] ="http://www.quanxue.cn/";
             char                 *ptr ="http://www.51minge.com/";
             char                 *point;

    point = str;  //将str數組的位址賦給指針變量point
    point[11] = \'Q\', point[15] = \'X\';
    printf("str=%s\n",str);

    ptr[13] = \'M\', ptr[16] = \'G\';  //這句是錯誤的,删除後結果如下      
printf("ptr=%s\n",ptr);

             return                 0;

}      
  1. char

     str[] = "http://www.quanxue.cn/";中str是數組變量,當位址賦給point之後,point[11]就是str[11],是以其内容可以改變。
  2. char

     *ptr = "http://www.51minge.com/";中指派的性質和上面的str不同。這并不是将"http://www.51minge.com/"賦給*ptr指針,而是先定義一個常量"http://www.51minge.com/",這個常量是定義在“棧”裡面,然後将這個常量的位址賦給ptr,而不是*ptr。常量是不能被修改的,是以ptr[13]也就出錯了。這是初學者經常犯的錯誤。
int                 i = 129;
             int                 num[] = {50, 25, 75, 100};

             int                 *pt1 = 125;    //錯誤1: 125作為位址賦給pt1,  這段記憶體是OS用的
             int                 *pt2 = i ;     //錯誤2: 129作為位址賦給pt2,  這段記憶體是OS用的
             int                 *pt3 = &i;     //正确:  變量i的位址賦給pt3,  因為i是基本類型,是以要加&符号
             int                 *pt4 = num;    //正确:  數組num的位址賦給pt4,因為num是數組,變量名就代表位址

             char                 *pt5 ;
   *pt5 ="ABCDE";     //錯誤3:  "ABCDE"是字元串,也是數組, 此處更是常量
    pt5 ="ABCDE";     //正确:   指派時賦的是位址,是以隻能賦給指針變量pt5

             int                 *pt6 ;
    pt6 =i;           //錯誤4:  129作為位址賦給pt6,  這段記憶體是OS用的
   *pt6 =i;           //錯誤5:  129賦給指針pt6,但pt6尚未配置設定位址,沒有空間存放i的值
      

不指派的指針和NULL

未指派的指針變量是不能被使用的,其位址指向未不能使用的空間。建議定義時如果暫不使用,先賦NULL。為一個指針申請空間時,一定義要判斷其是否為空,因為配置設定記憶體失敗時傳回NULL。不僅如此,甚至在使用指針時都應該判斷一下是否為空。下面講到的記憶體配置設定是重要内容,在下下章詳細介紹。

#include                 <stdio.h>
         #include                 <stdlib.h>

         int                 main(         void                )
{
             char                 *pchar;

    //下面這句出錯,忽略之後繼續
    printf("pchar=%p\n", pchar);  //未配置設定的指針不可用

    pchar = NULL;
    printf("pchar=%p\n\n", pchar);  //空指針可用于表達式中

    //pchar為空時,動态配置設定記憶體
             if                 (!pchar) {
        pchar = (         char                 *)malloc(20);  //動态配置設定記憶體
                 if                 (!pchar) {  //初學者不要忘記, 這是必要的判斷
            printf("記憶體配置設定失敗。");
            exit(-1);  //退出
        }
        gets(pchar);
        printf(" pchar=%p\n*pchar=%s\n", pchar, pchar);
        free(pchar);   //記憶體釋放後,指針變量的位址不變
                 if                 (pchar) {   //pchar并不為空
            printf("\n pchar=%p\n*pchar=%s\n", pchar, pchar);  //pchar成了“野指針”
        }
    }

             return                 0;
}

六、指針、數組和字元串      

一、數組和指針的關系

下面仍然是初學者容易搞錯的地方。指針變量加n或減n,并不是位址加n或減n,而是目前所指的位址向後或向前跳n次所指的位址。

#include                 <stdio.h>

         int                 main(         void                )
{
             int                 num[] = {50, 25, 75, 100};
             int                 *pt;

    pt = num + 1;   //故意将第2個元素位址賦給指針變量

    //顯示指針變量所指的位址以及指針的值
    printf("pt  =%d, *pt    =%d\n\n", pt,   *pt);

    //當指針變量減1或加1時,所指的位址并不減1或加1,而是加減4,因為int是4個位元組
    printf("pt-1=%d, *(pt-1)=%d\n", pt-1, *(pt-1));
    printf("pt  =%d, *pt    =%d\n", pt,   *pt);
    printf("pt+1=%d, *(pt+1)=%d\n", pt+1, *(pt+1));

    //顯示pt當作數組用時的值。(注意:[-1]仍然是正确的)
    printf("\npt[0]=%d, pt[-1]=%d\n", pt[0], pt[-1]);

             return                 0;
}      

二、指針數組

char型的指針數組相當于二維字元數組,并不等于說指針數組可以直接轉化為二為字元數組,相反字元數組可以直接轉化為指針數組。因為二維字元數組的位址是連續的,而指針數組所指的元素不一定連續(如下的m1、m2、m3的位址可以不連續,長度也可以不一樣)。

#include                 <stdio.h>

         int                 main(         void                )
{
             char                 *m1 ="www.quanxue.cn";
             char                 *m2 ="www.51minge.com";
             char                 *m3 ="這兒是小雅的C語言教程";

             char                 *message[3];                  //|           #include                 <stdio.h>
             int                 i;                             //|
                                       //|           int                 main(         void                )
    message[0] = m1;                   //|  {
    message[1] = m2;                   //|               char                 *message[] = {"www.quanxue.cn",
    message[2] = m3;                   //|"www.51minge.com",
                                       //|"這兒是小雅的C語言教程"};
             for                 (i=0; i<3; i++) {              //|               for                 (i=0; i<3; i++) {
        printf("%s\n", message[i]);    //|          printf("%s\n", message[i]);
    }                                  //|      }
                                       //|
             return                 0;                          //|               return                 0;
}                                      //|  }      

三、指向指針的指針

在第一章講main()函數的參數時,已經見過指針的指針,這和指針數組有相同的作用,但還是有細小的差別。指針數組可以在定義時直接初始化,而指向指針的指針不行。正如二維數組一樣,不指定第二維長度不能直接初始化一樣。即不能char str[][]={"...", "...", ...}

#include                 <stdio.h>

         int                 main(         void                )
{
             char                 *message[] = {"www.quanxue.cn","www.51minge.com","這兒是小雅的C語言教程"};
             char                 **p;       //指向指針的指針
             int                 i;

    p = message;    //指向指針的指針賦初值
             for                 (i=0; i<3; i++) {
        printf("%s\n", p[i]);
    }

             return                 0;
}      

四、指針的長度

讓許多初學者遺憾的是,C語言沒有提供數組長度的函數,但可以用sizeof()運算符先求數組的總長度,再求出數組類型的長度,二者相除便得到數組的長度。C語言更大的一個遺憾便是,sizeof()對指針變量求值時,結果總是4,這是因為指針變量的内容是位址,位址總是4個位元組來表示。

是以有經驗的程式設計人員,在用指針作參數時,一般總是同時多定義一個參數,來存放其長度。也就是指針和其長度同時傳遞過去。另外,數組長度如果事先知道,一般定義為常量。

#include                 <stdio.h>

         int                 main(         void                )
{
             char                 *msg[] = {"www.quanxue.cn","www.51minge.com","這兒是小雅的C語言教程"};
             double                 dNum[] = {12.5, 24.55, 100.83};
             double                 *p = dNum;

    printf("dNum的size:%2d, 數組個數是:%d\n",          sizeof                (dNum), (         int                )         sizeof                (dNum)/         sizeof                (         double                ));
    printf("   p的size:%2d, 數組個數是:%d\n",          sizeof                (p   ), (         int                )         sizeof                (p   )/         sizeof                (         double                ));
    printf(" msg的size:%2d, 數組個數是:%d\n",          sizeof                (msg ), (         int                )         sizeof                (msg )/         sizeof                (         char                 *));

             return                 0;
}

七、為指針動态配置設定記憶體      

C語言程式員要嚴防記憶體洩漏,這個“記憶體洩漏”就是由動态記憶體配置設定引起的。指針是C語言和其它語言的最大差別,也是很多人不能跨入C語言的一道門檻。既然指針是這麼一個“危險”的壞東西,幹嗎不取消它呢?

其實指針本身并沒有好壞,它隻是一種操作位址的方法,學會了便可以發揮其它語言難以匹敵的功能,沒學會的話,隻能做其它語言的程式員,也同樣發揮你的光和熱。小雅本人也在C語言門外徘徊多年,至今仍屬于初學者。

一、變量和數組可以通過指針來轉換

int

 *x”中的x究竟是不是數組?光看這一句小雅無法告訴你,因為它既可表示單個變量内容,也可表示數組。下面是小雅專門為你準備的例子,了解之後,對動态配置設定時長度計算有好處。

#include                 <stdio.h>

         int                 main(         void                )
{
             int                 *num = NULL;
             int                 *x, y[] = {12, 22,32}, z = 100;

    //下面示範,指針既可充當變量、也可充當數組
    x=&z;      //整型變量的位址賦給x
    printf("*x=%d, x[0]=%d\n", *x, x[0]);

    x = y;     //數組的位址賦給x
    printf("*x=%d, x[ 0]=%d, x[ 1]=%d, x[2]=%d\n", *x, x[0], x[1], x[2]);

    x = y + 1; //數組的第二位位址賦給x
    printf("*x=%d, x[-1]=%d, x[ 0]=%d, x[1]=%d\n", *x, x[-1], x[0], x[1]);

    x = y + 2; //數組的第三位位址賦給x
    printf("*x=%d, x[-2]=%d, x[-1]=%d, x[0]=%d\n", *x, x[-2], x[-1], x[0]);

             return                 0;
}      

二、動态配置設定記憶體

前面講到的指針,基本上将已經定義好的變量的位址賦給指針變量,現在要學的是向作業系統申請一塊新的記憶體。申請到的記憶體,必須在某個地方手動釋放,是以下面2個函數必須配對使用。malloc()和free(),都是标準函數,在stdlib.h中定義。

根據不同的電腦使用狀況,申請記憶體有可能失敗,失敗時傳回NULL,是以,動态申請記憶體時,一定要判斷結果是否為空。malloc()的傳回值類型是“void *”,是以,不要忘記類型轉換。(許多人都省略了。)

#include                 <stdio.h>
         #include                 <stdlib.h>
         #include                 <string.h>

         int                 main(         void                )
{
             char                 *p ;

    p = (         char                 *)malloc(40 *          sizeof                (         char                )) ;
             if                 (p == NULL) {          //這個判斷是必須的
        printf("記憶體配置設定出錯!");
        exit(1);
    }
    strcpy(p,"這是勸學網C語言教程。\n");   //不要忘記給新記憶體指派
    printf("%s", p);

    free(p);    //過河一定要拆橋
    p = NULL ;  //釋放後的指針置空,這是非常好的習慣,防止野指針。

         return                 0;
}      

三、隐蔽的記憶體洩漏

記憶體洩漏主要有以下幾種情況:

  1. 記憶體配置設定未成功,卻使用了它。
  2. 記憶體配置設定雖然成功,但是尚未初始化就引用它。
  3. 記憶體配置設定成功并且已經初始化,但操作越過了記憶體的邊界。
  4. 忘記了釋放記憶體,造成記憶體洩露。
  5. 釋放了記憶體卻繼續使用它。

下面的程式造成記憶體洩漏,想想錯在何處?如何修改?

#include                 <stdio.h>
         #include                 <stdlib.h>

         int                 main(         void                )
{
             int                 *p, i;

    p = (         int                 *)malloc(6 * sizeof(         int                )) ;
             if                 (p == NULL) {    //判斷是否為空
        printf("記憶體配置設定出錯!");
        exit(1);
    }

             for                 (i=0; i<6; i++) {
        p++;
        *p = i;
        printf("%2d", *p);      
}
    printf("\n");

    free(p);    //這句運作時出錯

             return                 0;
}      

四、對動态記憶體的錯誤觀念

有人對某一隻在函數内使用的指針動态配置設定了記憶體,用完後不釋放。其理由是:函數運作結束後,函數内的所有變量全部消亡。這是錯誤的。動态配置設定的記憶體是在“堆”裡定義,并不随函數結束而消亡。

有人對某動态配置設定了記憶體的指針,用完後直接設定為NULL。其理由是:已經為NULL了,這就釋放了。這也是錯誤的。指針可以任意指派,而記憶體并沒有釋放;相反,記憶體釋放後,指針也并不為NULL。

八、return和exit、assert的差別

return語句是結束目前函數。而exit是結束main()函數,即整個程式,一般都是在遇到非常錯誤時才調用exit()。assert()是一個宏定義,在assert.h中申明,用來在DEBUG方式診斷程式,當參數中的條件不成立時,中斷main()函數。建議多多使用assert()。

九、變量和函數

在函數之外定義的變量是全局變量,在函數内定義的變量是這個函數的局部變量。局部就是隻能在目前函數内使用,而全局變量可以在任何一個函數中使用。

注意:一般而言,全局變量總是在所有函數之前定義,但如果某全局變量定義在兩個函數之間,則定義處後面的函數可以使用,而其前面函數不能使用。

有人說靜态變量相當于全局變量,這句話其實不對。全局變量變成靜态,就失去了靜态的意義,是以,靜态一般是加在局部變量上的。那麼,究竟什麼是靜态的局部變量呢?靜态變量随函數的定義而定義,如果已經存在就延用,但并不随函數的結束而消亡。在某一函數中定義的靜态局部變量,不能在其它函數使用。

當很多人編寫同一程式時,一般程式會被分割成幾個檔案。當幾個人都定義了某一全局變量時,編譯時不出錯,Link時将出錯。解決這個問題的辦法:将其中一個定義原封不動,其餘的定義前加上extend(即外部的定義)。

剛才所說是許多書上說的,小雅做了n次試驗,證明上述編譯時也不錯,Link時也不錯,也就是說extend完全是多餘的。大概上面所說是幾十年前的版本吧。事實上與extend同列在一起的還有auto、regist等變量修飾符。auto是差別B語言的,早就沒用了,regist是将變量放到寄存器來運算,小雅認為基本沒有這種需要。

拆成多個檔案,多次定義全局變量時要注意:

  1. 變量的資料類型要一緻。
  2. 有長度的數組和沒定義長度的數組可以視為同一資料類型。
  3. 數組和指針不能視為同一資料類型。