C語言學習三至運算子、判斷、回圈和函數

2020-08-11 19:12:55

歡迎大家進羣一起學習,qq羣3:463345484
網路硬碟資料:鏈接:https://pan.baidu.com/s/1odgbx4gxSKqBkispTBxthg
提取碼:vi74

運算子是一種告訴編譯器執行特定的數學或邏輯操作的符號。C 語言內建了豐富的運算子,並提供了以下型別的運算子:

  • 算術運算子
  • 關係運算符
  • 邏輯運算子
  • 位運算子
  • 賦值運算子
  • 雜項運算子

算術運算子

下表顯示了 C 語言支援的所有算術運算子。假設變數 A 的值爲 10,變數 B 的值爲 20,則:

運算子 描述 範例
+ 把兩個運算元相加 A + B 將得到 30
- 從第一個運算元中減去第二個運算元 A - B 將得到 -10
* 把兩個運算元相乘 A * B 將得到 200
/ 分子除以分母 B / A 將得到 2
% 取模運算子,整除後的餘數 B % A 將得到 0
++ 自增運算子,整數值增加 1 A++ 將得到 11
-- 自減運算子,整數值減少 1 A-- 將得到 9

範例

請看下面 下麪的範例,瞭解 C 語言中所有可用的算術運算子:

 


#include <stdio.h>
 
int main()
{
   int a = 21;
   int b = 10;
   int c ;
 
   c = a + b;
   printf("Line 1 - c 的值是 %d\n", c );
   c = a - b;
   printf("Line 2 - c 的值是 %d\n", c );
   c = a * b;
   printf("Line 3 - c 的值是 %d\n", c );
   c = a / b;
   printf("Line 4 - c 的值是 %d\n", c );
   c = a % b;
   printf("Line 5 - c 的值是 %d\n", c );
   c = a++;  // 賦值後再加 1 ,c 爲 21,a 爲 22
   printf("Line 6 - c 的值是 %d\n", c );
   c = a--;  // 賦值後再減 1 ,c 爲 22 ,a 爲 21
   printf("Line 7 - c 的值是 %d\n", c );
 
}

當上面的程式碼被編譯和執行時,它會產生下列結果:

Line 1 - c 的值是 31
Line 2 - c 的值是 11
Line 3 - c 的值是 210
Line 4 - c 的值是 2
Line 5 - c 的值是 1
Line 6 - c 的值是 21
Line 7 - c 的值是 22

變數++,表示先使用變數,在+1,;而++變數,表示先+1,再使用變數。以下範例演示了 a++ 與 ++a 的區別:


#include <stdio.h>
 
int main()
{
   int c;
   int a = 10;
   c = a++; 
   printf("先賦值後運算:\n");
   printf("Line 1 - c 的值是 %d\n", c );
   printf("Line 2 - a 的值是 %d\n", a );
   a = 10;
   c = a--; 
   printf("Line 3 - c 的值是 %d\n", c );
   printf("Line 4 - a 的值是 %d\n", a );
 
   printf("先運算後賦值:\n");
   a = 10;
   c = ++a; 
   printf("Line 5 - c 的值是 %d\n", c );
   printf("Line 6 - a 的值是 %d\n", a );
   a = 10;
   c = --a; 
   printf("Line 7 - c 的值是 %d\n", c );
   printf("Line 8 - a 的值是 %d\n", a );
 
}

以上程式執行輸出結果爲:

先賦值後運算:
Line 1 - c 的值是 10
Line 2 - a 的值是 11
Line 3 - c 的值是 10
Line 4 - a 的值是 9
先運算後賦值:
Line 5 - c 的值是 11
Line 6 - a 的值是 11
Line 7 - c 的值是 9
Line 8 - a 的值是 9

關係運算符

下表顯示了 C 語言支援的所有關係運算符。假設變數 A 的值爲 10,變數 B 的值爲 20,則:

運算子 描述 範例
== 檢查兩個運算元的值是否相等,如果相等則條件爲真。 (A == B) 爲假。
!= 檢查兩個運算元的值是否相等,如果不相等則條件爲真。 (A != B) 爲真。
> 檢查左運算元的值是否大於右運算元的值,如果是則條件爲真。 (A > B) 爲假。
< 檢查左運算元的值是否小於右運算元的值,如果是則條件爲真。 (A < B) 爲真。
>= 檢查左運算元的值是否大於或等於右運算元的值,如果是則條件爲真。 (A >= B) 爲假。
<= 檢查左運算元的值是否小於或等於右運算元的值,如果是則條件爲真。 (A <= B) 爲真。

請看下面 下麪的範例,瞭解 C 語言中所有可用的關係運算符:


#include <stdio.h>
 
int main()
{
   int a = 21;
   int b = 10;
   int c ;
 
   if( a == b )
   {
      printf("Line 1 - a 等於 b\n" );
   }
   else
   {
      printf("Line 1 - a 不等於 b\n" );
   }
   if ( a < b )
   {
      printf("Line 2 - a 小於 b\n" );
   }
   else
   {
      printf("Line 2 - a 不小於 b\n" );
   }
   if ( a > b )
   {
      printf("Line 3 - a 大於 b\n" );
   }
   else
   {
      printf("Line 3 - a 不大於 b\n" );
   }
   /* 改變 a 和 b 的值 */
   a = 5;
   b = 20;
   if ( a <= b )
   {
      printf("Line 4 - a 小於或等於 b\n" );
   }
   if ( b >= a )
   {
      printf("Line 5 - b 大於或等於 a\n" );
   }
}

當上面的程式碼被編譯和執行時,它會產生下列結果:

Line 1 - a 不等於 b
Line 2 - a 不小於 b
Line 3 - a 大於 b
Line 4 - a 小於或等於 b
Line 5 - b 大於或等於 a

邏輯運算子

下表顯示了 C 語言支援的所有關係邏輯運算子。假設變數 A 的值爲 1,變數 B 的值爲 0,則:

運算子 描述 範例
&& 稱爲邏輯與運算子。如果兩個運算元都非零,則條件爲真。 (A && B) 爲假。
|| 稱爲邏輯或運算子。如果兩個運算元中有任意一個非零,則條件爲真。 (A || B) 爲真。
! 稱爲邏輯非運算子。用來逆轉運算元的邏輯狀態。如果條件爲真則邏輯非運算子將使其爲假。 !(A && B) 爲真。

請看下面 下麪的範例,瞭解 C 語言中所有可用的邏輯運算子:


#include <stdio.h>
 
int main()
{
   int a = 5;
   int b = 20;
   int c ;
 
   if ( a && b )
   {
      printf("Line 1 - 條件爲真\n" );
   }
   if ( a || b )
   {
      printf("Line 2 - 條件爲真\n" );
   }
   /* 改變 a 和 b 的值 */
   a = 0;
   b = 10;
   if ( a && b )
   {
      printf("Line 3 - 條件爲真\n" );
   }
   else
   {
      printf("Line 3 - 條件爲假\n" );
   }
   if ( !(a && b) )
   {
      printf("Line 4 - 條件爲真\n" );
   }
}

當上面的程式碼被編譯和執行時,它會產生下列結果:

Line 1 - 條件爲真
Line 2 - 條件爲真
Line 3 - 條件爲假
Line 4 - 條件爲真

位運算子

位運算子作用於位,並逐位執行操作。&、 | 和 ^ 的真值表如下所示:

p q p & q p | q p ^ q
0 0 0 0 0
0 1 0 1 1
1 1 1 1 0
1 0 0 1 1

假設如果 A = 60,且 B = 13,現在以二進制格式表示,它們如下所示:

A = 0011 1100

B = 0000 1101

-----------------

A&B = 0000 1100

A|B = 0011 1101

A^B = 0011 0001

~A  = 1100 0011

下表顯示了 C 語言支援的位運算子。假設變數 A 的值爲 60,變數 B 的值爲 13,則:

運算子 描述 範例
&

按位元與操作,按二進制位進行"與"運算。運算規則:

0&0=0;   
0&1=0;    
1&0=0;     
1&1=1;
(A & B) 將得到 12,即爲 0000 1100
|

按位元或運算子,按二進制位進行"或"運算。運算規則:

0|0=0;   
0|1=1;   
1|0=1;    
1|1=1;
(A | B) 將得到 61,即爲 0011 1101
^

互斥或運算子,按二進制位進行"互斥或"運算。運算規則:

0^0=0;   
0^1=1;   
1^0=1;  
1^1=0;
(A ^ B) 將得到 49,即爲 0011 0001
~

取反運算子,按二進制位進行"取反"運算。運算規則:

~1=0;   
~0=1;
(~A ) 將得到 -61,即爲 1100 0011,一個有符號二進制數的二補數形式。
<< 二進制左移運算子。將一個運算物件的各二進制位全部左移若幹位(左邊的二進制位丟棄,右邊補0)。 A << 2 將得到 240,即爲 1111 0000
>> 二進制右移運算子。將一個數的各二進制位全部右移若幹位,正數左補0,負數左補1,右邊丟棄。 A >> 2 將得到 15,即爲 0000 1111

請看下面 下麪的範例,瞭解 C 語言中所有可用的位運算子:


#include <stdio.h>
 
int main()
{
 
   unsigned int a = 60;    /* 60 = 0011 1100 */  
   unsigned int b = 13;    /* 13 = 0000 1101 */
   int c = 0;           
 
   c = a & b;       /* 12 = 0000 1100 */ 
   printf("Line 1 - c 的值是 %d\n", c );
 
   c = a | b;       /* 61 = 0011 1101 */
   printf("Line 2 - c 的值是 %d\n", c );
 
   c = a ^ b;       /* 49 = 0011 0001 */
   printf("Line 3 - c 的值是 %d\n", c );
 
   c = ~a;          /*-61 = 1100 0011 */
   printf("Line 4 - c 的值是 %d\n", c );
 
   c = a << 2;     /* 240 = 1111 0000 */
   printf("Line 5 - c 的值是 %d\n", c );
 
   c = a >> 2;     /* 15 = 0000 1111 */
   printf("Line 6 - c 的值是 %d\n", c );
}

當上面的程式碼被編譯和執行時,它會產生下列結果:

Line 1 - c 的值是 12
Line 2 - c 的值是 61
Line 3 - c 的值是 49
Line 4 - c 的值是 -61
Line 5 - c 的值是 240
Line 6 - c 的值是 15

賦值運算子

下表列出了 C 語言支援的賦值運算子:

運算子 描述 範例
= 簡單的賦值運算子,把右邊運算元的值賦給左邊運算元 C = A + B 將把 A + B 的值賦給 C
+= 加且賦值運算子,把右邊運算元加上左邊運算元的結果賦值給左邊運算元 C += A 相當於 C = C + A
-= 減且賦值運算子,把左邊運算元減去右邊運算元的結果賦值給左邊運算元 C -= A 相當於 C = C - A
*= 乘且賦值運算子,把右邊運算元乘以左邊運算元的結果賦值給左邊運算元 C *= A 相當於 C = C * A
/= 除且賦值運算子,把左邊運算元除以右邊運算元的結果賦值給左邊運算元 C /= A 相當於 C = C / A
%= 求模且賦值運算子,求兩個運算元的模賦值給左邊運算元 C %= A 相當於 C = C % A
<<= 左移且賦值運算子 C <<= 2 等同於 C = C << 2
>>= 右移且賦值運算子 C >>= 2 等同於 C = C >> 2
&= 按位元與且賦值運算子 C &= 2 等同於 C = C & 2
^= 按位元互斥或且賦值運算子 C ^= 2 等同於 C = C ^ 2
|= 按位元或且賦值運算子 C |= 2 等同於 C = C | 2

請看下面 下麪的範例,瞭解 C 語言中所有可用的賦值運算子:


#include <stdio.h>
 
main()
{
   int a = 21;
   int c ;
 
   c =  a;
   printf("Line 1 - =  運算子範例,c 的值 = %d\n", c );
 
   c +=  a;
   printf("Line 2 - += 運算子範例,c 的值 = %d\n", c );
 
   c -=  a;
   printf("Line 3 - -= 運算子範例,c 的值 = %d\n", c );
 
   c *=  a;
   printf("Line 4 - *= 運算子範例,c 的值 = %d\n", c );
 
   c /=  a;
   printf("Line 5 - /= 運算子範例,c 的值 = %d\n", c );
 
   c  = 200;
   c %=  a;
   printf("Line 6 - %= 運算子範例,c 的值 = %d\n", c );
 
   c <<=  2;
   printf("Line 7 - <<= 運算子範例,c 的值 = %d\n", c );
 
   c >>=  2;
   printf("Line 8 - >>= 運算子範例,c 的值 = %d\n", c );
 
   c &=  2;
   printf("Line 9 - &= 運算子範例,c 的值 = %d\n", c );
 
   c ^=  2;
   printf("Line 10 - ^= 運算子範例,c 的值 = %d\n", c );
 
   c |=  2;
   printf("Line 11 - |= 運算子範例,c 的值 = %d\n", c );
 
}

當上面的程式碼被編譯和執行時,它會產生下列結果:

Line 1 - =  運算子範例,c 的值 = 21
Line 2 - += 運算子範例,c 的值 = 42
Line 3 - -= 運算子範例,c 的值 = 21
Line 4 - *= 運算子範例,c 的值 = 441
Line 5 - /= 運算子範例,c 的值 = 21
Line 6 - %= 運算子範例,c 的值 = 11
Line 7 - <<= 運算子範例,c 的值 = 44
Line 8 - >>= 運算子範例,c 的值 = 11
Line 9 - &= 運算子範例,c 的值 = 2
Line 10 - ^= 運算子範例,c 的值 = 0
Line 11 - |= 運算子範例,c 的值 = 2

雜項運算子 ↦ sizeof & 三元

下表列出了 C 語言支援的其他一些重要的運算子,包括 sizeof? :

運算子 描述 範例
sizeof() 返回變數的大小。 sizeof(a) 將返回 4,其中 a 是整數。
& 返回變數的地址。 &a; 將給出變數的實際地址。
* 指向一個變數。 *a; 將指向一個變數。
? : 條件表達式 如果條件爲真 ? 則值爲 X : 否則值爲 Y

請看下面 下麪的範例,瞭解 C 語言中所有可用的雜項運算子:


#include <stdio.h>
 
int main()
{
   int a = 4;
   short b;
   double c;
   int* ptr;
 
   /* sizeof 運算子範例 */
   printf("Line 1 - 變數 a 的大小 = %lu\n", sizeof(a) );
   printf("Line 2 - 變數 b 的大小 = %lu\n", sizeof(b) );
   printf("Line 3 - 變數 c 的大小 = %lu\n", sizeof(c) );
 
   /* & 和 * 運算子範例 */
   ptr = &a;    /* 'ptr' 現在包含 'a' 的地址 */
   printf("a 的值是 %d\n", a);
   printf("*ptr 是 %d\n", *ptr);
 
   /* 三元運算子範例 */
   a = 10;
   b = (a == 1) ? 20: 30;
   printf( "b 的值是 %d\n", b );
 
   b = (a == 10) ? 20: 30;
   printf( "b 的值是 %d\n", b );
}

當上面的程式碼被編譯和執行時,它會產生下列結果:

Line 1 - 變數 a 的大小 = 4
Line 2 - 變數 b 的大小 = 2
Line 3 - 變數 c 的大小 = 8
a 的值是 4
*ptr 是 4
b 的值是 30
b 的值是 20

C 中的運算子優先順序

運算子的優先順序確定表達式中項的組合。這會影響到一個表達式如何計算。某些運算子比其他運算子有更高的優先順序,例如,乘除運算子具有比加減運算子更高的優先順序。

例如 x = 7 + 3 * 2,在這裏,x 被賦值爲 13,而不是 20,因爲運算子 * 具有比 + 更高的優先順序,所以首先計算乘法 3*2,然後再加上 7。

下表將按運算子優先順序從高到低列出各個運算子,具有較高優先順序的運算子出現在表格的上面,具有較低優先順序的運算子出現在表格的下面 下麪。在表達式中,較高優先順序的運算子會優先被計算。

類別  運算子  結合性 
後綴  () [] -> . ++ - -   從左到右 
一元  + - ! ~ ++ - - (type)* & sizeof  從右到左 
乘除  * / %  從左到右 
加減  + -  從左到右 
移位  << >>  從左到右 
關係  < <= > >=  從左到右 
相等  == !=  從左到右 
位與 AND  從左到右 
位互斥或 XOR  從左到右 
位或 OR  從左到右 
邏輯與 AND  &&  從左到右 
邏輯或 OR  ||  從左到右 
條件  ?:  從右到左 
賦值  = += -= *= /= %=>>= <<= &= ^= |=  從右到左 
逗號  從左到右

請看下面 下麪的範例,瞭解 C 語言中運算子的優先順序:


#include <stdio.h>
 
main()
{
   int a = 20;
   int b = 10;
   int c = 15;
   int d = 5;
   int e;
 
   e = (a + b) * c / d;      // ( 30 * 15 ) / 5
   printf("(a + b) * c / d 的值是 %d\n",  e );
 
   e = ((a + b) * c) / d;    // (30 * 15 ) / 5
   printf("((a + b) * c) / d 的值是 %d\n" ,  e );
 
   e = (a + b) * (c / d);   // (30) * (15/5)
   printf("(a + b) * (c / d) 的值是 %d\n",  e );
 
   e = a + (b * c) / d;     //  20 + (150/5)
   printf("a + (b * c) / d 的值是 %d\n" ,  e );
  
   return 0;
}

當上面的程式碼被編譯和執行時,它會產生下列結果:

(a + b) * c / d 的值是 90
((a + b) * c) / d 的值是 90
(a + b) * (c / d) 的值是 90
a + (b * c) / d 的值是 50

C 判斷

判斷結構要求程式設計師指定一個或多個要評估或測試的條件,以及條件爲真時要執行的語句(必需的)和條件爲假時要執行的語句(可選的)。

C 語言把任何非零非空的值假定爲 true,把null 假定爲 false

判斷語句

C 語言提供了以下型別的判斷語句。點選鏈接檢視每個語句的細節。

語句 描述
if 語句 一個 if 語句 由一個布爾表達式後跟一個或多個語句組成。
if...else 語句 一個 if 語句 後可跟一個可選的 else 語句,else 語句在布爾表達式爲假時執行。
巢狀 if 語句 您可以在一個 ifelse if 語句內使用另一個 ifelse if 語句。
switch 語句 一個 switch 語句允許測試一個變數等於多個值時的情況。
巢狀 switch 語句 您可以在一個 switch 語句內使用另一個 switch 語句。

 

? : 運算子(三元運算子)

我們已經在前面的章節中講解了 條件運算子 ? :,可以用來替代 if...else 語句。它的一般形式如下:

Exp1 ? Exp2 : Exp3;

其中,Exp1、Exp2 和 Exp3 是表達式。請注意,冒號的使用和位置。

? 表達式的值是由 Exp1 決定的。如果 Exp1 爲真,則計算 Exp2 的值,結果即爲整個 ? 表達式的值。如果 Exp1 爲假,則計算 Exp3 的值,結果即爲整個 ? 表達式的值。

以下範例通過輸入一個數字來判斷它是否爲奇數或偶數:


#include<stdio.h>
 
int main()
{
    int num;
 
    printf("輸入一個數字 : ");
    scanf("%d",&num);
 
    (num%2==0)?printf("偶數"):printf("奇數");
}

C 回圈

有的時候,我們可能需要多次執行同一塊程式碼。一般情況下,語句是按順序執行的:函數中的第一個語句先執行,接着是第二個語句,依此類推。

程式語言提供了更爲複雜執行路徑的多種控制結構。

回圈語句允許我們多次執行一個語句或語句組。

回圈型別

C 語言提供了以下幾種回圈型別。點選鏈接檢視每個型別的細節。

回圈型別 描述
while 回圈 當給定條件爲真時,重複語句或語句組。它會在執行回圈主體之前測試條件。
for 回圈 多次執行一個語句序列,簡化管理回圈變數的程式碼。
do...while 回圈 除了它是在回圈主體結尾測試條件外,其他與 while 語句類似。
巢狀回圈 您可以在 while、for 或 do..while 回圈內使用一個或多個回圈。

 

回圈控制語句

回圈控制語句改變你程式碼的執行順序。通過它你可以實現程式碼的跳轉。

C 提供了下列的回圈控制語句。點選鏈接檢視每個語句的細節。

控制語句 描述
break 語句 終止回圈switch 語句,程式流將繼續執行緊接着回圈或 switch 的下一條語句。
continue 語句 告訴一個回圈體立刻停止本次回圈迭代,重新開始下次回圈迭代。
goto 語句 將控制轉移到被標記的語句。但是不建議在程式中使用 goto 語句。

 

無限回圈

如果條件永遠不爲假,則回圈將變成無限回圈。for 回圈在傳統意義上可用於實現無限回圈。由於構成回圈的三個表達式中任何一個都不是必需的,您可以將某些條件表達式留空來構成一個無限回圈。


#include <stdio.h>
 
int main ()
{
   for( ; ; )
   {
      printf("該回圈會永遠執行下去!\n");
   }
   return 0;
}

當條件表達式不存在時,它被假設爲真。您也可以設定一個初始值和增量表達式,但是一般情況下,C 程式設計師偏向於使用 for(;;) 結構來表示一個無限回圈。

注意:您可以按 Ctrl + C 鍵終止一個無限回圈。

C 函數

函數是一組一起執行一個任務的語句。每個 C 程式都至少有一個函數,即主函數 main() ,所有簡單的程式都可以定義其他額外的函數。

您可以把程式碼劃分到不同的函數中。如何劃分程式碼到不同的函數中是由您來決定的,但在邏輯上,劃分通常是根據每個函數執行一個特定的任務來進行的。

函數宣告告訴編譯器函數的名稱、返回型別和參數。函數定義提供了函數的實際主體。

C 標準庫提供了大量的程式可以呼叫的內建函數。例如,函數 strcat() 用來連線兩個字串,函數 memcpy() 用來複制記憶體到另一個位置。

函數還有很多叫法,比如方法、子例程或程式,等等。

定義函數

C 語言中的函數定義的一般形式如下:

return_type function_name( parameter list )
{
   body of the function
}

在 C 語言中,函數由一個函數頭和一個函數主體組成。下面 下麪列出一個函數的所有組成部分:

  • 返回型別:一個函數可以返回一個值。return_type 是函數返回的值的數據型別。有些函數執行所需的操作而不返回值,在這種情況下,return_type 是關鍵字 void
  • 函數名稱:這是函數的實際名稱。函數名和參數列表一起構成了函數簽名。
  • 參數:參數就像是佔位符。當函數被呼叫時,您向參數傳遞一個值,這個值被稱爲實際參數。參數列表包括函數參數的型別、順序、數量。參數是可選的,也就是說,函數可能不包含參數。
  • 函數主體:函數主體包含一組定義函數執行任務的語句。

以下是 max() 函數的原始碼。該函數有兩個參數 num1 和 num2,會返回這兩個數中較大的那個數:


/* 函數返回兩個數中較大的那個數 */
int max(int num1, int num2) 
{
   /* 區域性變數宣告 */
   int result;
 
   if (num1 > num2)
      result = num1;
   else
      result = num2;
 
   return result; 
}

函數宣告

函數宣告會告訴編譯器函數名稱及如何呼叫函數。函數的實際主體可以單獨定義。

函數宣告包括以下幾個部分:

return_type function_name( parameter list );

針對上面定義的函數 max(),以下是函數宣告:

int max(int num1, int num2);

在函數宣告中,參數的名稱並不重要,只有參數的型別是必需的,因此下面 下麪也是有效的宣告:

int max(int, int);

當您在一個原始檔中定義函數且在另一個檔案中呼叫函數時,函數宣告是必需的。在這種情況下,您應該在呼叫函數的檔案頂部宣告函數。

呼叫函數

建立 C 函數時,會定義函數做什麼,然後通過呼叫函數來完成已定義的任務。

當程式呼叫函數時,程式控制權會轉移給被呼叫的函數。被呼叫的函數執行已定義的任務,當函數的返回語句被執行時,或到達函數的結束括號時,會把程式控制權交還給主程式。

呼叫函數時,傳遞所需參數,如果函數返回一個值,則可以儲存返回值。例如:


#include <stdio.h>
 
/* 函數宣告 */
int max(int num1, int num2);
 
int main ()
{
   /* 區域性變數定義 */
   int a = 100;
   int b = 200;
   int ret;
 
   /* 呼叫函數來獲取最大值 */
   ret = max(a, b);
 
   printf( "Max value is : %d\n", ret );
 
   return 0;
}
 
/* 函數返回兩個數中較大的那個數 */
int max(int num1, int num2) 
{
   /* 區域性變數宣告 */
   int result;
 
   if (num1 > num2)
      result = num1;
   else
      result = num2;
 
   return result; 
}

把 max() 函數和 main() 函數放一塊,編譯原始碼。當執行最後的可執行檔案時,會產生下列結果:

Max value is : 200

函數參數

如果函數要使用參數,則必須宣告接受參數值的變數。這些變數稱爲函數的形式參數

形式參數就像函數內的其他區域性變數,在進入函數時被建立,退出函數時被銷燬。

當呼叫函數時,有兩種向函數傳遞參數的方式:

呼叫型別 描述
傳值呼叫 該方法把參數的實際值複製給函數的形式參數。在這種情況下,修改函數內的形式參數不會影響實際參數。
參照呼叫 通過指針傳遞方式,形參爲指向實參地址的指針,當對形參的指向操作時,就相當於對實參本身進行的操作。

預設情況下,C 使用傳值呼叫來傳遞參數。一般來說,這意味着函數內的程式碼不能改變用於呼叫函數的實際參數。

C 作用域規則

任何一種程式設計中,作用域是程式中定義的變數所存在的區域,超過該區域變數就不能被存取。C 語言中有三個地方可以宣告變數:

  1. 在函數或塊內部的區域性變數
  2. 在所有函數外部的全域性變數
  3. 形式參數的函數參數定義中

讓我們來看看什麼是區域性變數、全域性變數和形式參數。

區域性變數

在某個函數或塊的內部宣告的變數稱爲區域性變數。它們只能被該函數或該程式碼塊內部的語句使用。區域性變數在函數外部是不可知的。下面 下麪是使用區域性變數的範例。在這裏,所有的變數 a、b 和 c 是 main() 函數的區域性變數。


#include <stdio.h>
 
int main ()
{
  /* 區域性變數宣告 */
  int a, b;
  int c;
 
  /* 實際初始化 */
  a = 10;
  b = 20;
  c = a + b;
 
  printf ("value of a = %d, b = %d and c = %d\n", a, b, c);
 
  return 0;
}

全域性變數

全域性變數是定義在函數外部,通常是在程式的頂部。全域性變數在整個程式生命週期內都是有效的,在任意的函數內部能存取全域性變數。

全域性變數可以被任何函數存取。也就是說,全域性變數在宣告後整個程式中都是可用的。下面 下麪是使用全域性變數和區域性變數的範例:


#include <stdio.h>
 
/* 全域性變數宣告 */
int g;
 
int main ()
{
  /* 區域性變數宣告 */
  int a, b;
 
  /* 實際初始化 */
  a = 10;
  b = 20;
  g = a + b;
 
  printf ("value of a = %d, b = %d and g = %d\n", a, b, g);
 
  return 0;
}

在程式中,區域性變數和全域性變數的名稱可以相同,但是在函數內,如果兩個名字相同,會使用區域性變數值,全域性變數不會被使用。下面 下麪是一個範例:

在程式中,區域性變數和全域性變數的


#include <stdio.h>
 
/* 全域性變數宣告 */
int g = 20;
 
int main ()
{
  /* 區域性變數宣告 */
  int g = 10;
 
  printf ("value of g = %d\n",  g);
 
  return 0;
}

當上面的程式碼被編譯和執行時,它會產生下列結果:

value of g = 10

形式參數

函數的參數,形式參數,被當作該函數內的區域性變數,如果與全域性變數同名它們會優先使用。下面 下麪是一個範例:


#include <stdio.h>
 
/* 全域性變數宣告 */
int a = 20;
 
int main ()
{
  /* 在主函數中的區域性變數宣告 */
  int a = 10;
  int b = 20;
  int c = 0;
  int sum(int, int);
 
  printf ("value of a in main() = %d\n",  a);
  c = sum( a, b);
  printf ("value of c in main() = %d\n",  c);
 
  return 0;
}
 
/* 新增兩個整數的函數 */
int sum(int a, int b)
{
    printf ("value of a in sum() = %d\n",  a);
    printf ("value of b in sum() = %d\n",  b);
 
    return a + b;
}

當上面的程式碼被編譯和執行時,它會產生下列結果:

value of a in main() = 10
value of a in sum() = 10
value of b in sum() = 20
value of c in main() = 30

全域性變數與區域性變數在記憶體中的區別

  • 全域性變數儲存在記憶體的全域性儲存區中,佔用靜態的儲存單元;
  • 區域性變數儲存在棧中,只有在所在函數被呼叫時才動態地爲變數分配儲存單元。

初始化區域性變數和全域性變數

當區域性變數被定義時,系統不會對其初始化,您必須自行對其初始化。定義全域性變數時,系統會自動對其初始化,如下所示:

數據型別 初始化預設值
int 0
char '\0'
float 0
double 0
pointer NULL

正確地初始化變數是一個良好的程式設計習慣,否則有時候程式可能會產生意想不到的結果,因爲未初始化的變數會導致一些在記憶體位置中已經可用的垃圾值。