C語言中文網 目錄

C語言指針作為參數和返回值

C 語言本質上是傳值調用(call by value)的語言,因為函數的形參都是局部變量,它們通過傳入的實參進行初始化。

C 語言的優點是,只要表達式的類型適當,就可以當作實參。另一方面,缺點是在啟用函數時,如需要復制大數據對象,則運行成本很高。而且,函數沒有辦法修改原始變量(調用者的變量),只能修改原始變量的復制版本。

然而,如果函數的實參是變量的地址,那么函數就可以通過指針,直接獲取該原始變量,并修改原始變量的值。所以,C 語言也提供了傳址調用(call by reference)函數。

一個典型的例子就是標準函數 scanf(),它從標準輸入流中讀入數據,然后將結果放在它的變量中,該變量由調用者提供的指針參數所引用:
int var;
scanf( "%d", &var );

該函數調用會將字符串當作十進制數讀入,然后轉換為整數,再將它的值存儲在局部變量 var 的內存地址上。

下面的函數 initNode()初始化一個結構變量。調用者將該結構的地址當作參數來傳遞。
#include <string.h>                    // 包含了memset() 和 strcpy()的原型
struct Node { long key;
              char name[32];
              /* ... 更多結構化的成員 ... */
              struct Node *next;
           };
void initNode( struct Node *pNode )     // 初始化*pNode結構
{
  memset( pNode, 0, sizeof(*pNode) );
  strcpy( pNode->name, "XXXXX" );
}

即使函數只需要讀取變量的值,而不需要修改變量,傳遞變量地址仍然在許多時候更為高效。這是因為傳遞地址可以避免復制數據,只有變量地址會被推入棧中。

如果函數不修改變量,那么應該將對應的參數聲明成只讀指針,如下面的例子所示:
void printNode( const struct Node *pNode );
{
  printf( "Key: %ld\n", pNode->key );
  printf( "Name: %s\n", pNode->name );
  /* ... */
}

當在調用函數時把數組名作為參數,那么也是在進行“傳址調用”,因為數組名會自動地被轉換為指向數組內第一個元素的指針。

通常情況下,函數需要返回指針,如下例函數 mkNode()。該函數動態地建立一個新的 Node 對象,并將其地址傳遞給調用者:
#include <stdlib.h>
struct Node *mkNode()
{
  struct Node *pNode = malloc( sizeof(struct Node) );
  if ( pNode != NULL )
    initNode( pNode );
  return pNode;
}

如果無法為新的 Node 對象分配存儲空間,則函數 mkNode()會返回一個空指針。返回指針的函數通常采用返回空指針來表示失敗。例如,一個搜索函數,如果找到了滿足條件的對象,則返回該對象的地址,如果沒有找到滿足條件的對象,則返回空指針。

精美而實用的網站,提供C語言、C++、STL、Linux、Shell、Java、Go語言等教程,以及socket、GCC、vi、Swing、設計模式、JSP等專題。

Copyright ?2011-2018 biancheng.net, 陜ICP備15000209號

底部Logo
极速pk10开户