標準C程序設計(四)

9 用戶自定義函數
   9.1 返回多個值的函數
   一般我們使用return語句只能返回一個值,假設我們需要從函數中獲得更多的信息該怎麼辦?在C語言中,我們可以使用參數,不僅接收信息,而且還往調用函數返回信息。用於返回信息的參數稱爲輸出參數。
使用地址運算符(&)和間接運算符(*)可以實現。如下:
void mathoperation(int x, int y, int *sum, int *diff);
int main(int argc, char const *argv[])
{
     int x = 20, y = 10, s, d;
     mathoperation( x, y, &S, &d );
     printf("s = %d d = %d  \n", s, d );
}
void mathoperation(int x, int y, int *sum, int *diff)
{
     *sum = x + y;
     *diff = x - y;
}
   該函數的第一條語句x和y的值相加,結果保存在sum指向的存儲位置。記住,該存儲位置就是s的存儲位置。因此,保存在由sum指向的存儲位置中的值就是s的值。
用指針進行傳遞的規則:
  • 實參和形參的類型必須相同
  • 實參(在函數調用中)必須是變量(他是調用函數的局部變量)的地址
  • 函數頭中的形參必須以間接運算符*爲前綴
  • 在函數原型中,其參數也必須以*爲前綴
  • 要在被調用函數中訪問實參的值,必須使用相應的以間接運算符*爲前綴的形參
按值傳遞和指針傳遞:
  • 按值傳遞:實參的值被複製給被調用函數參數列表中的變量。被調用函數使用的是實參的副本,而不是其原始值。這就確保調用函數的原始值不被隨意修改。
  • 按指針傳遞:發送給被調用函數的是變量的地址,而不是值的副本。在這種情況下,被調用函數是直接作用於調用函數的數據,因此,調用函數可以使用已修改的值。如操作數組和字符串時,經常使用;或者需要被調用函數返回多個值時。
9.2 變量的作用域、可見性、生存期
     在C語言中,變量不僅屬於某種數據類型,而且還具有某種存儲類型。
  1.  自動變量是在某個函數中生命的變量,當調用該函數時創建變量,函數推出時自動銷燬。自動變量是所在函數的私有(局部)變量,又稱局部或內部變量。默認情況下,如果生命在某個函數中的變量沒有指定存儲類型,則爲自動變量。
  2. 整個程序中都是存在並且活動的變量稱爲外部變量,或全局變量。與局部變量不同的是,他可以被程序的所有函數訪問。它在函數的外面進行聲明。
  • 如果局部變量與全局變量同名,那麼在聲明局部變量的函數中,局部變量具有比全局變量更高的優先級
  • 一旦全局變量聲明後,任何函數都可以使用和修改其值,這樣,後面它的函數就只能引用其新值了
  • 只有從全局變量的聲明之處開始到程序的末尾可用。
  • 全局變量默認的初始化爲0
      3. 外部聲明:在聲明的程序段中,main函數不能訪問變量y,因爲他是在main函數的後面聲明的。通過使用存儲類型extern來聲明變量,就可以解決這個問題。
int main(int argc, char const *argv[])
{
     extern int y; //外部聲明
     return 0;
}
func()
{
     extern int y;
}
int y; //聲明全局變量
func1()
{
     y = y + 1;
}
      4. 靜態變量的值可以一直保持到程序結束。使用static可以將變量聲明爲靜態的。可以分爲內部類型和外部類型。
  • 在某個函數中生命的爲內部靜態變量。內部static變量類似於auto,只不過auto變量在程序其餘部分仍保持有效
void stat(void);
int main(int argc, char const *argv[])          
{
     int i;
     for ( i = 0; i < 4; ++i)
     {
          stat();
     }
     system("pause");
     return 0;
}
void stat()
{
     static int x = 0;
     x++;
     printf("x = %d\n", x );
}
  • 外部static變量聲明在所有函數之外,因此對程序的所有函數都可用。static外部變量與簡單外部變量的區別是,staitc外部變量只在定義他的文件中可用,而簡單外部變量可以被其他文件訪問。
     5. 寄存器變量可以告訴編譯器,某個變量應保存在寄存器中而不是內存(普通變量保存在這裏)。由於訪問寄存器要比內存快很多,把經常要訪問的變量(如循環控制變量)保存在寄存器中可以加快程序的運行速度。
       register int count;(大多數編譯器只允許把int和char類型的變量保存在寄存器中)
9.3 多文件程序
     實際的程序中,一般包含多個源文件,這些文件被分別編譯,然後連接成一個可運行的目標代碼。只要把變量聲明爲外部變量,多個源文件就可以共享它。被兩個或多個文件共享的變量稱爲全局變量,因此必須在某個文件中進行相應的聲明,然後再其他文件中顯示的用extern進行引用。
在test_35.c中main函數可以引用變量m,該變量在test_36.c中聲明爲全局的。但是,函數func1不能訪問變量m。因爲extern語句在main函數內部,如果extern語句放在main函數之前,或者在每個函數中都使用了extern語句,那麼每個函數都可以訪問變量m。
       extern說明符告訴編譯器,後面的變量類型和名稱已經在其他地方進行了聲明,不用爲他們創建存儲空間了。由鏈接器去解決。注意,多文件全局變量只能是在某一個文件(而且只有一個)中不帶extern說明符進行聲明。如果在兩個不同文件(這兩個文件被一個程序使用)中把一個變量聲明爲全局變量,那麼鏈接器將產生一個衝突,不知道該使用那個變量,因此發出一個警告。
       當一個函數定義在某個文件中,被另一個文件訪問,那麼在第二個文件中必須包含該函數的聲明。該聲明表明該函數是一個外部函數,其定義出現在其他的地方。我們通常把這種聲明放在文件的開始處,位於所有函數之前。儘管所有函數都假定爲外部的,但良好的習慣是在函數聲明時顯示的使用extern。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章