【正文】
有被給定一個值就被使用的變量。堆開始時也很小,但當程序員調用 malloc()或 calloc()等內存分配函數時它就會增大。在象 DOS這樣的沒有虛擬內存 (virtual memory)的系統中,這個界限由系統決定,并且通常非常大,因此程序員不必擔心用盡棧空間。 在函數內部定義的 auto變量 (沒有用關鍵字 static定義的變量 )的生存期從程序開始執(zhí)行其所在的程序塊 代碼時開始,到程序離開該程序塊時為止。第三種是動態(tài)分配的數據的生存期,它從程序調用 malloc()或 calloc()為數據分配存儲空間時開始,到程序調用 free()或程序退出時為 止。 auto 變量的作用域為從定義點到該局部程序塊尾部。 作用域有三種: 1. extern(外部的 ) 這是在函數外部定義的變量的缺省存儲方式。 上例將輸出字符串 cfilorux,即字母表中序號為 3的倍數的所有字母。 for(x= 1。 這個表達式的結果為 15除以 7 的余數,等于 1。 1. 14 取模運算符 (modulus operator)“% ”的作用是什么 ? 取模運算符 “ % ” 的作用是求兩個數相除的余數。 x=1。 x=1。如果 “++” 運算符出現在變量之后 (var++),那么先對表達式求值,然后變量的值才增加 1。因此,你應該用括號明確地指定運算符的優(yōu)先級。 /* the{unction void—function—call() returns nothing */ 如果上例中的函數返回一個整數,那么它可以被看作一個右值,因為它的返回值可以存儲 到左值 x中。 x = 1。 ... 在上例中,結構變量 my_name 的全部內容被拷貝到結構變量 your_name 中,其作用和下述語句是相同的: memcpy(your_name, my_name, sizeof(your_name)。你可以把一個結構變量賦給另一個同類型的結構變量,例如: typedef struct t_name { charlast_name[25]; char first_name[15]。 x=y; 不過,你可以通過 for 循環(huán)來遍歷數組中的每個元素,并分別對它們賦值,例如: int i; int x[5]。因此,這兩條賦值語句中沒有左值,編譯程序會指出它們是錯誤的。注意,在第二個賦值語句 “*p_int = 5中,通過 “*” 修飾符 訪問 p_int 所指向的內存區(qū)域;因此, p_int 是一個左值。 int *p_int。左值位于賦值語句的左側,與其相對的右值 (rvaule,見 1. 11)則位于賦值語句的右側。s previous state has been restored. \n)。 void call_ longjmp (void)。然而,使用這兩個函數有一個很大的缺陷,當程序恢復到它原來所保存的狀態(tài)時,它將失去對所有在 longjmp()和 setjmp()之間動態(tài)分配的內存的控制,也就是說這將浪費所有在 longjmp()和 setjmp()之間用 malloc()和 calloc()分配所得的內存,從而使程序的效率大大降低。 } 前面已經提到, longjmp()和 setjmp()函數實現程序執(zhí)行中的遠程跳轉。下面就是一個改進了實現的例子: void better_function (void) { int x printf(Excuse me while I count to 5000... \n)。 x=l; while (1) { printf( %d\n, x) if (x ==5000) goto all_done else x=x+1。 goto 語句會跳過程序中的一段代碼并轉到一個預先指定的位置。緊接著循環(huán)的 if 語句用來測試循環(huán)次數,從而判斷循環(huán)是否提前結束。請看下例: int x char * cp[REQUESTED_BLOCKS] / * Attempt (in vain, I must add... )to allocate 512 10KB blocks in memory. * / for (x = 0。逗號左邊 是第一個表達式,它把 0至 99之間的一個隨機數賦給 i;第二個表達式在 while 語句中更常見,它是一個條件表達式,用來判斷 i是否不等于 50。 (2)j 自增。 / * Here, the while statement uses the ma operator to assign the value of i as well as test it. * / while (i=(rand() % 100), i !=50)/*隨即數 */ printf(i is %d, trying again... \n, i) printf (\nGuess what? i is 50!\n ) } 請注意下述語句: i: (j++, k++) 這條語句一次完成了三個動作,依次為: (1)把 k 值賦給 i。 / * Notice how you can use the ma operator to perform multiple initializations on the same line. * / i=0, j=1, k=2。此外,目前大多數優(yōu)化編譯程序都會忽略最后一條 break 語句,所以加入這條語句不會影響程序的性能。例如,如果用 switch 語句來處理數目固定的條件,而且認為這些條件之外的值都屬于邏輯錯誤,那么可以加入一個 default 分支來辨識邏輯錯誤。: printf (You answered NO!\n)。: printf ( You answered YES ! \n ) break case 39。t a clue as to what your name means. \n)。 else if(!stricmp(name, Lloyd)) printf(Your name means39。. \n)。 } 注意,使用 switch 語句的前提是條件表達式必須基于同一個數字型變量。x is equal to three. \n)。 不如使用下述代碼 ,它更易于閱讀和維護: switch (x) { case 1: printf (x is equal to one. \n)。例如,與其使用下述代碼: if (x ==l) printf (x is equal to one. \n)。例如,為了調試程序,你可能要說明一個全局變量的局部實例,以便在相應的函數體內部進行測試。 printf ( Test variable within the independent local block: %d\n, test_var) } / * End independent local block * / printf (Test variable after the if statement: %d\n, test_var)。 printf(Test variable before the if statement: %d\n, test_var)。你可以在局部程序塊中說明一些變量,這種變量被稱為局部變量,它們只能在局部程序塊的開始部分說明,并且只在說明它的局部程序塊中有效。 1. 1 什么是局部程序塊 (local block)? 局部程序塊是指一對大括號 ({})之間的一段 C語言程序。本章將回答這方面你經常會遇到的一些問題。當你開始編寫 C 程序時,你可能對 C語言的一些基本問題感到困惑,如 C 語言所使用的約定、關鍵字和術語等。在閱讀本章時,請注意有關 switch 語句和運算符優(yōu)先級的一些問題,這些問題常常會使 C 語言的初學者感到迷惑。此外,你完全可以創(chuàng)建你自己的局部程序塊,而不使用 C函數或基本的 C 語句。 void main() { / * Begin local block for function main() * / int test_ var = 10。 { / * Begin independent local block (not tied to any function or keyword) * / int test_var = 0。 請參見: 1. 2可以把變量保存在局部程序塊中嗎 ? 1. 2 可以把變量保存在局部程序塊中嗎 ? 用局部程序塊來保存變量是不常見的,你應該盡量避免這樣做,但也有極少數的例外。 請參見: 1. 1 什么是局部程序塊 ? 1. 3 什么時候用一條 switch語句比用多條 if 語句更好 ? 如果你有兩個以上基于同一個數字 (numeric)型變量的條件表達式,那么最好使用一條switch 語句。 else printf (x is not equal to one, two, or three. \n)。 break case 3: printf (39。 break。Laughter39。. \n)。 else printf(I haven39。y39。n39。 4 break ...... 此外, default 分支能給邏輯檢查帶來很多方便。在每個分支后面加上 break 語句將防止發(fā)生這種錯誤并增強程序的安全性。 void main () { / * Here, the ma operator is used to separate three variable declarations. * / int i, j, k。 printf(i=%d, j=%d, k=%d\n, i, j, k)。如果所用的表達式是 ++k,則 ++k 的值會被賦給 i,因為 ++k 是一個前綴自增表達式, k的自增發(fā)生在賦值操作之前。 這里,逗號運算符將兩個表達式隔開, while 語句的每次循環(huán)都將計算這兩個表達式的值。 請參見: 1. 12 運算符的優(yōu)先級總能保證是 “自左至右 ”或 “自右至左 ”的順序嗎 ? 1. 13 ++var 和 var++有什么區(qū)別 ? 6 1. 7 怎樣才能知道循環(huán)是否提前結束了 ? 循環(huán)通常依賴于一個或多個變量, 你可以在循環(huán)外檢查這些變量,以確保循環(huán)被正確執(zhí)行。 注意,如果上述循環(huán)執(zhí)行成功,它一定會循環(huán) 512 次。通常你應該避免任何形式的執(zhí)行中跳轉,因為在程序中使用 goto 語句或 longjmp()函數不是一種好的編程習慣。下面是一個使用 goto 語句的例子: void bad_programmers_function(void) { int x printf(Excuse me while I count to 5000... \n) 。 } 7 如果不使用 goto 語句,是例可以編寫得更好。t so bad, was it?\n) 。與 goto 語句不同, longjmp()和 setjmp()函數實現的跳轉不一定在同一個函數內。 void main(void)。 ret_code = setjmp (saved_state) if (ret_code ==1) { printf(The longjmp function has been called. \n ) printf(The program39。return to the previous program state... \n ) call_ longjmp ( ) } void call_longjmp (void) { longjmp (saved_state, 1 ) } 8 1. 9 什么是左值 (lvaule)? 左值是指可以被賦值的表