C語言編程常見問題集之數組

來源:互聯網
上載者:User

(隔段時間不看就會在實際使用中忘記掉---c語言數組、異或指標的使用),轉載一下,忘時供查詢

 C語言處理數組的方式是它廣受歡迎的原因之一。C語言對數組的處理是非常有效,其原因有以下三點:
    第一,除少數翻譯器出于謹慎會作一些繁瑣的規定外,C語言的數組下標是在一個很低的層次上處理的。但這個優點也有一個反作用,即在程式運行時你無法知道一個數組到底有多大,或者一個數組下標是否有效。ANSI/ISOC標準沒有對使用越界下標的行為作出定義,因此,一個越界下標有可能導致這樣幾種後果:
    (1) 程式仍能正確運行;
    (2) 程式會異常終止或崩潰;
    (3) 程式能繼續運行,但無法得出正確的結果;
    (4) 其它情況。
    換句話說,你不知道程式此後會做出什麼反應,這會帶來很大的麻煩。有些人就是抓住這一點來批評C語言的,認為C語言只不過是一種進階的組合語言。然而,儘管C程式出錯時的表現有些可怕,但誰也不能否認一個經過仔細編寫和調試的C程式運行起來是非常快的。
    第二,數組和指標能非常和諧地在一起工作。當數組出現在一個運算式中時,它和指向數組中第一個元素的指標是等價的,因此數組和指標幾乎可以互換使用。此外,使用指標要比使用數組下標快兩倍(請參見9.5中的例子)。
    第三,將數組作為參數傳遞給函數和將指向數組中第一個元素的指標傳遞給函數是完全·
    等價的。將數組作為參數傳遞給函數時可以採用值傳遞和地址傳遞兩種方式,前者需要完整地拷貝初始數組,但比較安全;後者的速度要快得多,但編寫程式時要多加小心。C++和ANSIC中都有const要害字,利用它可以使地址傳遞方式和值傳遞方式一樣安全。假如你想瞭解更多的細節,請參見2.4,8.6和第7章“指標和記憶體配置”開頭部分的介紹。
    數組和指標之間的這種聯絡會引起一些混亂,例如以下兩種定義是完全相同的:
    void f(chara[MAX])
    {
        /*...  */
    }
    void f(char *a)
    {    ·
        /*...  */
    }
    注重:MAX是一個編譯時間可知的值,例如用#define預先處理指令定義的值。
    這種情況正是前文中提到的第三個優點,也是大多數C程式員所熟知的。這也是唯一一種數組和指標完全相同的情況,在其它情況下,數組和指標並不完全相同。例如,當作如下定義 (可以出現在函數說明以外的任何地方)時:
    char    a[MAX];
  系統將分配MAX個字元的記憶體空間。當作如下說明時:
    char   *a;
  系統將分配一個字元指標所需的記憶體空間,可能只能容納2個或4個字元。假如你在源檔案中作如下定義:
    char    a[MAX];
  但在標頭檔作如下說明;
    extern char   *a;
  就會導致可怕的後果。為了避免出現這種情況,最好的辦法是保證上述說明和定義的一致性,例如,假如在源檔案中作如下定義:
    char    a[MAX];
  那麼在相應的標頭檔中就作如下說明,
    externchar    a[];
  上述說明告訴標頭檔a是一個數組,不是一個指標,但它並不指示數組a中有多少個元素,這樣說明的類型稱為不完整類型。在程式中適當地說明一些不完整類型是很常見的,也是一種很好的編程習慣。

    9.1  數組的下標總是從0開始嗎?
   是的,對數組a[MAX](MAX是一個編譯時間可知的值)來說,它的第一個和最後一個元素分別是a[o]和aLMAX-1)。在其它一些語言中,情況可能有所不同,例如在BASIC語言中數組a[MAX]的元素是從a[1]到a[MAX],在Pascal語言中則兩種方式都可行。
    注重:a[MAX]是一個有效地址,但該地址中的值並不是數組a的一個元素(見9。2)。
    上述這種差別有時會引起混亂,因為當你說“數組中的第一個元素”時,實際上是指“數組中下標為。的元素”,這裡的“第一個”的意思和“最後一個”相反。
    儘管你可以假造一個下標從1開始的數組,但在實際編程中不應該這樣做。下文將介紹這種技巧,並說明為什麼不應該這樣做的原因。
    因為指標和數組幾乎是相同的,因此你可以定義一個指標,使它可以象一個數組一樣引用另一個數組中的所有元素,但引用時前者的下標是從1開始的:
    /*don't do this!!*/
    int a0[MAX],
    int *a1=a0-1; /*&a0[-1)*/
    現在,a0[0]和a1[1)是相同的,而a0[MAX-1]和a1[MAX]是相同的。然而,在實際編程中不應該這樣做,其原因有以下兩點:
    第一,這種方法可能行不通。這種行為是ANSI/ISOC標準所沒有定義的(並且是應該避免的),而&a0[-1)完全有可能不是一個有效地址(見9.3)。對於某些編譯器,你的程式可能根本不會出問題;在有些情況下,對於任何編譯器,你的程式可能都不會出問題;但是,誰能保證你的程式永遠不會出問題呢?   

    第二,這種方式背離了C語言的常規風格。人們已經習慣了C語言中數組下標的工作方式,假如你的程式使用了另外一種方式,別人就很難讀懂你的程式,而經過一段時間以後,連你自己都可能很難讀懂這個程式了。

    請參見:
    9.2 可以使用數組後面第一個元素的地址嗎?
    9.3 為什麼要小心對待位於數組後面的那些元素的地址呢?

    9.2  可以使用數組後面第一個元素的地址嗎?
    你可以使用數組後面第一個元素的地址,但你不可以查看該地址中的值。對大多數編譯器來說,假如你寫如下語句:
    int    i,a[MAX],j;
  那麼i和j都有可能存放在數組a最後一個元素後面的地址中。為了判定跟在數組a後面的是i還是j,你可以把i或j的地址和數組a後面第一個元素的地址進行比較,即判定"&i==&a[MAX]"或"&j==&a[MAX]"是否為真。這種方法通常可行,但不能保證。
    問題的要害是:假如你將某些資料存入a[MAX]中,往往就會破壞原來緊跟在數組a後面的資料。即使查看a[MAX]的值也是應該避免的,儘管這樣做一般不會引出什麼問題。
    為什麼在C程式中有時要用到&a[MAX]呢?因為很多C程式員習慣通過指標遍曆一個數組中的所有元素,即用
    for(i=0;i<MAX;++i)
    {   
        /*do something*/
    }
  代替
    for(p=a; p<&a[MAX];++p)
    {
        /*do something*/
    }
    這種方式在已有的C程式中是隨處可見的,因此ANSIC標準規定這種方式是可行的。

    請參見:
    9.3 為什麼要小心對待位於數組後面的那些元素的地址呢?
    9.5 通過指標或帶下標的數組名都可以訪問數組中的元素,哪一種方式更好呢?

     9.3  為什麼要小心對待位於數組後面的那些元素的地址呢?
     假如你的程式是在理想的電腦上運行,即它的取址範圍是從00000000到FFFFFFFF,那麼你大可以放心,但是,實際情況往往不會這麼簡單。
    在有些電腦上,地址是由兩部分組成的,第一部分是一個指向某一塊記憶體的起始點的指,針(即基地址),第二部分是相對於這塊記憶體的起始點的地 址位移量。這種地址結構被稱為段地址結構,子程式調用通常就是通過在棧指標上加上一個地址位移量來實現的。採用段地址結構的最典型的例子是基於Intel 8086的電腦,所有的MS-DOS程式都在這種電腦上運行(在基於Pentium晶片的電腦上,大多數MS-DOS程式也在與8086相容的模式下運行)。即使是效能優越的具有線性地址空間的RISC晶片,也提供了寄存器變址定址方式,即用一個寄存器儲存指向某一塊記憶體的起始點的指標,用另一個寄存器儲存地址位移量。
    假如你的程式使用段地址結構,而在基地址處剛好存放著數組a0(即基地址指標和&a0[0]相同),這會引出什麼問題呢?既然基地址無法(有效地)改變,而位移量也不可能是負值,因此“位於a0[0]前面的元素”這種說法就沒有意義了,ANSIC標準明確規定引用這個元素的行為是沒有定義的,這也就是9.1中所提到的方法可能行不通的原因。
    同樣,假如數組a(其元素個數為MAX)剛好存放在某段記憶體的尾部,那麼地址&a[MAX]就是沒有意義的,假如你的程式中使用了&a[MAX],而編譯器又要檢查&a[MAX]是否有效,那麼編譯器必然就會報告沒有足夠的記憶體來存放數組a。
    儘管在編寫基於Windows,UNIX或Macintosh的程式時不會碰到上述問題,但是C語言不僅僅是為這幾種情況設計的,C語言必須適應各種各樣的環境,例如用微處理器控制的烤麵包爐,防抱死刹車系統,MS-DOS,等等。嚴格按C語言標準編寫的程式能被順利地編譯並能服務於任何目的,但是,有時程式員也可以適度地背離C語言的標準,這要視程式員、編譯器和程式使用者三者的具體要求而定。
    請參見:
    9. 1數組的下標總是從0開始嗎?
    9.2可以使用數組後面第一個元素的地址嗎?

    9.4  在把數組作為參數傳遞給函數時,可以通過sizeof運算子告訴函數數組的大小嗎?
    不可以。當把數組作為函數的參數時,你無法在程式運行時通過數組參數本身告訴函數該數組的大小,因為函數的數組參數相當於指向該數組第一個元素的指標。這意味著把數組傳遞給函數的效率非常高,也意味著程式員必須通過某種機制告訴函數數組參數的大小。
    為了告訴函數數組參數的大小,人們通常採用以下兩種方法:
    第一種方法是將數組和表示數組大小的值一起傳遞給函數,例如memcpy()函數就是這樣做的:
    char  source[MAX],dest[MAX];
    /*...  */
    memcpy(dest,source,MAX);
    第二種方法是引入某種規則來結束一個數組,例如在C語言中字串總是以ASCII字元NUL('\0')結束,而一個指標數組總是以null 指標結束。請看下述函數,它的參數是一個以空指
  針結束的字元指標數組,這個null 指標告訴該函數什麼時候停止工作:
    void printMany(char *strings口)   
    {
        int  i;
        i=0;   
        while(strings[i]!=NULL)
        {
            puts(strings[i]);
            ++i;
        }
    }
    正象9.5中所說的那樣,C程式員經常用指標來代替數組下標,因此大多數C程式員通常會將上述函數編寫得更隱蔽一些:
    void printMany(char *strings[])
    {
        while(*strings)
        {
            puts(*strings++);
        }
    }
    儘管你不能改變一個數組名的值,但是strings是一個數組參數,相當於一個指標,因此可以對它進行自增運算,並且可以在調用puts()函數時對strings進行自增運算。在上例中,while(*strings)
    就相當於
    while(*strings !=NULL)
    在寫函數文檔(例如在函數前面加上注釋,或者寫一份備忘錄,或者寫一份設計文檔)時,寫進函數是如何知道數組參數的大小是非常重要的,例如,你可以非常簡略地寫上“以null 指標結束”或“數組elephants中有numElephants個元素”(假如你在程式中用數字13表示數組的大小,你可以寫進“數組arr中有13個元素”這樣的描述,然而用確切的數字表示數組的大小不是一種好的編程習慣)。

    請參見:
    9.5通過指標或帶下標的數組名都可以訪問數組中的元素,哪一種方式更好呢?
    9.6可以把另外一個地址賦給一個數組名嗎?   

    9.5  通過指標或帶下標的數組名都可以訪問數組中的元素,哪一種方式更好呢?
    與使用下標相比,使用指標能使C編譯器更輕易地產生優質的代碼。
    假設你的程式中有這樣一段代碼:

/* X la some type */
X      a[MAX];            
X      *p;    /*pointer*/
X      x;     /*element*/
int    i;     /*index*/

為了曆數組a中的所有元素,你可以採用這樣一種迴圈方式(方式a)
/*version (a)*/
for (i = 0; i<MAX;  ++i)
{
      x=a[i];
      /* do something with x * /
}
你也可以採用這樣一種迴圈方式(方式b)
/*veraion(b)*/
for (p = a; p<&a[MAX];  ++p   )
{
      x=*p;
      /* do aomething with x * /
}
    這兩種方式有什麼區別呢?兩種方式中的初始情況和遞增運算是相同的,作為迴圈條件的比較運算式也是相同的(下文中將進一步討論這一點)。區別在於“x=a[]”和“x=*p”,前者要確定a[i]的地址,因此需要將i和類型x的大小相乘後再與數組a中第一個元素的地址相加;
後者只需間接引用指標p。間接引用是快速的,而乘法運算卻比較慢。
    這是一種“微效率”現象,它可能對程式的總體效率有影響,也可能沒有影響。對方式a來說,假如迴圈體中的操作是將數組中的元素相加,或者只是移動數組中的元素,那麼每次迴圈中大部分時間就消耗在使用數組下標上;假如迴圈體中的操作是某種I/O操作,或者是函數調用,那麼使用數組下標所消耗的時間是微不足道的。
    在有些情況下,乘法運算的開銷會降低。例如,當類型x的大小為1時,經過最佳化就可以將乘法運算省去(一個值乘以1仍然等於這個值);當類型x的大小是2的冪時(此時類型x通常是系統固有類型),乘法運算就可以被最佳化為左移位元運算(就象一個十進位的數乘以10一樣)。
    在方式b中,每次迴圈都要計算&a[MAX],這需要多大代價呢?這和每次計算a[i]的代價相同嗎?答案是不同,因為在迴圈過程中&a[MAX]是不變的。任何一種合格的編譯器都只會在迴圈開始時計算一次&a[MAX],而在以後的每次迴圈中重複使用這次計算所得的值。
在編譯器確認在迴圈過程中a和MAX都不變的前提下,方式b和以下代碼的效果是相同的:
/* how the compiler implements version (b) */
X      *temp =  &a[MAX];     /* optimization */
for (p = a; p< temp; ++p  )
{
    x =*p;
    /*do something with x * /
}

    遍曆數組元素還可以有另外兩種方式,即以遞減而不是遞增的順序遍曆數組元素。對按順序列印數組元素這樣的任務來說,後兩種方式沒有什麼優勢,但是對數組元素相加這樣的任務來說,後兩種方式 比前兩種方式更好。通過下標並且以遞減順序遍曆數組元素的方式(方式c)如下所示(人們通常認為將一個值和。比較的代價要比將一個值和一個非零值比較的代價小:

/* version (c) */
for (i = MAX - 1; i>=0; --i)

{
      x=a[i];
      /* do aomcthing with x * /
}

    通過指標並以遞減順序遍曆數組元素的方式(方式d)如下所示,其中作為迴圈條件的比較運算式顯得很簡潔:

/* version (d) */
for (p = &a[MAX - 1]; p>=a;  --p  )
{
      x =*P;
      /*do something with x * /
}

    與方式d類似的代碼是很常見的,但不是絕對正確的,因為迴圈結束的條件是p小於a,而這有時是不可能的(見9.3)。
    通常人們會認為“任何合格的能最佳化代碼的編譯器都會為這4種方式產生相同的代碼”,但實際上許多編譯器都沒能做到這一點。筆者曾編寫過一個測試程式(其中類型x的大小不是2的冪,迴圈體中的操作是一些無關緊要的操作),並用4種差別很大的編譯器編譯這個程式,結果發現方式b總是比方式a快得多,有時要快兩倍,可見使用指標和使用下標的效果是有很大差別的(有一點是一致的,即4種編譯器都對&a[MAX]進行了前文提到過的最佳化)。
    那麼在遍曆數組元素時,以遞減順序進行和以遞增順序進行有什麼不同呢?對於其中的兩種編譯器,方式c和方式d的速度基本上和方式a相同,而方式b明顯是最快的(可能是因為其比較操作的代價較小,但是否可以認為以遞減順序進行要比以遞增順序進行慢一些呢?);
  對於其中的另外兩種編譯器,方式c的速度和方式a基本相同(使用下標要慢一些),但方式d的速度比方式b要稍快一些。
    總而言之,在編寫一個可移植性好、效率高的程式時,為了遍曆數組元素,使用指標比使用下標能使程式獲得更快的速度;在使用指標時,應該採用方式b,儘管方式d一般也能工作,但編譯器為方式d產生的代碼可能會慢一些。 

    需要補充的是,上述技巧只是一種細微的最佳化,因為通常都是迴圈體中的操作消耗了大部分已耗用時間,許多C程式員往往會舍本求末,忽視這種實際情況,希望你不要犯相同的錯誤。

請參見:   
    9.2可以使用數組後第一個元素的地址嗎?   
    9.3為什麼要小心對待位於數組後面的那些元素的地址呢?

    9.6  可以把另外一個地址賦給一個數組名嗎?
    不可以,儘管在一個很常見的特例中好象可以這樣做。
    數組名不能被放在賦值運算子的左邊(它不是一個左值,更不是一個可修改的左值)。一個數組是一個對象,而它的數組名就是指向這個對象的第一個元素的指標。   
    假如一個數組是用extern或static說明-的,則它的數組名是在串連時可知的一個常量,你不能修改這樣一個數組名的值,就象你不能修改7的值一樣。
    給數組名賦值是毫無根據的。一個指標的含義是“這裡有一個元素,它的前後可能還有其它元素”,一個數組名的含義是“這裡是一個數組中的第一個元素,它的前面沒有數組元素,並且只有通過數組下標才能引用它後面的數組元素”。因此,假如需要使用指標,就應該使用指標。
    有一個很常見的特例,在這個特例中,好象可以修改一個數組名的值:
    void f(chara[12])
    {
        ++a;  /*legal!*/
    }
    秘密在於函數的數組參數並不是真正的數組,而是實實在在的指標,因此,上例和下例是等價的:
    void f(char *a)
    {
        ++a;  /*certainlylegal*/
    }
    假如你希望上述函數中的數組名不能被修改,你可以將上述函數寫成下面這樣,但為此你必須使用指標句法:
    void{(char *const a)
    {
        ++a;  /*illegal*/
    }
    在上例中,參數a是一個左值,但它前面的const要害字說明了它是不能被修改的。

    請參見:
    9. 4在把數組作為參數傳遞給函數時,可以通過sizeof運算子告訴函數數組的大小嗎?
   
    9.7 array_name和&array_name有什麼不同?
    前者是指向數組中第一個元素的指標,後者是指向整個數組的指標。
    注重;筆者建議讀者讀到這裡時暫時放下本書,寫一下指向一個含MAX個元素的字元數組的指標變數的說明。提示:使用括弧。希望你不要敷衍了事,因為只有這樣你才能真正瞭解C語言表示複雜指標的句法的奧秘。下文將介紹如何獲得指向整個數組的指標。
    數組是一種類型,它有三個要素,即基本類型(數組元素的類型),大小(當數組被說明為不完整類型時除外),數組的值(整個數組的值)。你可以用一個指標指向整個數組的值:
    char  a[MAX];    /*arrayOfMAXcharacters*/
    char    *p;      /*pointer to one character*/
    /*pa is declared below*/
    pa=&al
    p=a;             /* =&a[0] */
    在運行了上述這段代碼後,你就會發現p和pa的列印結果是一個相同的值,即p和pa指向同一個地址。但是,p和pa指向的對象是不同的。
    以下這種定義並不能獲得一個指向整個數組的值的指標:
    char *(ap[MAX]);
    上述定義和以下定義是相同的,它們的含義都是“ap是一個含MAX個字元指標的數組”;
    char *ap[MAX];

    9.8  為什麼用const說明的常量不能用來定義一個數組的初始大小?
    並不是所有的常量都可以用來定義一個數組的初始大小,在C程式中,只有C語言的常量運算式才能用來定義一個數組的初始大小。然而,在C++中,情況有所不同。
    一個常量運算式的值在程式運行期間是不變的,並且是編譯器能計算出來的一個值。在定義數組的大小時,你必須使用常量運算式,例如,你可以使用數字:
    char    a[512];
    或者使用一個預定義的常量標識符:
    #define MAX    512
    /*...  */
    char    a[MAX];
    或者使用一個sizeof運算式:
    char  a[sizeof(structcacheObject)];
    或者使用一個由常量運算式組成的運算式:
    char    buf[sizeof(struct cacheObject) *MAX];
    或者使用枚舉常量。
    在C中,一個初始化了的constint變數並不是一個常量運算式:
    int    max=512;    /* not a constant expression in C */
    char  buffer[max];  /* notvalid C */
然而,在C++中,用const int變數定義數組的大小是完全合法的,並且是C++所推薦的。儘管這會增加C++編譯器的負擔(即跟蹤const int變數的值),而C編譯器沒有這種負擔,但這也使C++程式擺脫了對C預先處理程式的依靠。

    請參見;
    9.1數組的下標總是從0開始嗎?
    9.2可以使用數組後面第一個元素的地址嗎?

    9.9  字串和數組有什麼不同?
    數組的元素可以是任意一種類型,而字串是一種非凡的數組,它使用了一種眾所周知的確定其長度的規則。
    有兩種類型的語言,一種簡單地將字串看作是一個字元數組,另一種將字串看作是一種非凡的 類型。C屬於前一種,但有一點補充,即C字串是以一個NUL字元結束的。數組的值和數組中第一個元素的地址(或指向該元素的指標)是相同的,因此通常一個C字串和一個字元指標是等價的。
    一個數組的長度可以是任意的。當數組名用作函數的參數時,函數無法通過數組名本身知道數組的大小,因此必須引入某種規則。對字串來說,這種規則就是字串的最後一個字元是ASCII字元NUL('\0')。
    在C中,int類型值的字面值可以是42這樣的值,字元的字面值可以是‘*’這樣的值,浮點型值的字面值可以是4.2el這樣的單精確度值或雙精確度值。
    注重:實際上,一個char類型字面值是一個int類型字面值的另一種表示方式,只不過使用了一種有趣的句法,例如當42和'*'都表示char類型的值時,它們是兩個完全相同的值。然而,在C++中情況有所不同,C++有真正的char類型字面值和char類型函數參數,並且通常會更仔細地區分char類型和int類型。
  ,整數數組和字元數組沒有字面值。然而,假如沒有字串字面值,程式編寫起來就會很困難,因此C提供了字串字面值。需要注重的是,按照慣例C字串總是以NUL字元結束,因此C字串的字面值也以NUL字元結束,例如,“six times nine”的長度是15個字元(包括NUL終止符),而不是你看得見的14個字元。
    關於字串字面值還有一條鮮為人知但非常有用的規則,假如程式中有兩條緊挨著的字串字面值,編譯器會將它們當作一條長的字串字面值來對待,並且只使用一個NUL終止符。也就是說,“Hello,”world”和“Hello,world”是相同的,而以下這段代碼中的幾條字串字面值也可以任意分割組合:
    char    message[]=
    ”This is an extremely long prompt\n”
    ”How long is it?\n”
    ”It's so long,\n”
    ”It wouldn't fit On one line\n”;
    在定義一個字串變數時,你需要有一個足以容納該字串的數組或者指標,並且要保證為NUL終止符留出空間,例如,以下這段代碼中就有一個問題:
    char greeting[12];
    strcpy(greeting,”Hello,world”);  /*trouble*/
    在上例中,greeting只有容納12個字元的空間,而“Hello,world”的長度為13個字元(包括NUL終止符),因此NUL字元會被拷貝到greeting以外的某個位置,這可能會毀掉greetlng四周記憶體空間中的某些資料。再請看下例:
    char  greeting[12]=”Hello,world”;/*notastring*/
    上例是沒有問題的,但此時greeting是一個字元數組,而不是一個字串。因為上例沒有為NUL終止符留出空間,所以greeting不包含NUL字元。更好一些的方法是這樣寫:
    char  greeting[]=”Hello,world”;
    這樣編譯器就會計算出需要多少空間來容納所有內容,包括NUL字元。
    字串字面值是字元(char類型)數組,而不是字元常量(const char類型)數組。儘管ANSIC委員會可以將字串字面值重新定義為字元常量數組,但這會使已有的數百萬行代碼忽然無法通過編譯,從而引起巨大的混亂。假如你試圖修改字串字面值中的內容,編譯器是
    不會阻止你的,但你不應該這樣做。編譯器可能會選擇禁止修改的記憶體地區來存放字串字面值,例如ROM或者由記憶體映射寄存器禁止寫操作的記憶體地區。但是,即使字串字面值被存放在答應修改的記憶體地區中,編譯器還可能會使它們被共用。例如,假如你寫了以下代碼(並且字串字面值是答應修改的):
    char    *p="message";
    char    *q="message";
    p[4]='\0'; /* p now points to”mess”*/
    編譯器就會作出兩種可能的反應,一種是為p和q建立兩個獨立的字串,在這種情況下,q仍然是“message”;一種是只建立一個字串(p和q都指向它),在這種情況下,q將變成“mess”。
    注重:有人稱這種現象為“C的幽默”,正是因為這種幽默,絕大多數C程式員才會整天被自己編寫的程式所困擾,難得忙裡偷閒一次。

本文章來自www.21shipin.com  21視頻教程網

C語言編程常見問題集之數組_C語言程式設計教程 原文連結:http://www.21shipin.com/html/61368.shtml

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.