C語言中指標的應用



C語言最重要的特性之一是它提供了透過指標的概念來訪問底層記憶體的能力。指標是一個變數,它儲存記憶體中另一個變數的地址。

指標的提供有很多應用,例如將陣列和結構體型別傳遞給函式以及動態記憶體分配等。在本章中,我們將解釋C語言中指標的一些重要應用。

訪問陣列元素

也可以透過指標訪問陣列元素。您需要宣告並初始化一個指向陣列的指標,並使用它透過將指標變數遞增1來訪問每個元素。

指向陣列的指標是其第0個元素的地址。當陣列指標遞增1時,它指向陣列中的下一個元素。

示例

以下示例演示瞭如何藉助其指標遍歷陣列。

#include <stdio.h>

int main(){

   int arr[] = {1,2,3,4,5};
   int *ptr = arr;

   for(int i = 0; i <= 4; i++){
      printf("arr[%d]: %d\n", i, *ptr);
      ptr++;
   }
   
   return 0;
}

輸出

執行程式碼並檢查其輸出 -

arr[0]: 1
arr[1]: 2
arr[2]: 3
arr[3]: 4
arr[4]: 5

動態分配記憶體

C指標最重要的應用之一是動態宣告變數的記憶體。在各種情況下,靜態記憶體分配無法解決問題,例如處理大型陣列、包含n個學生和員工的結構體等。

因此,無論何時需要動態分配記憶體,指標在其中都起著重要作用。C語言提供了一些函式來動態分配和釋放記憶體。這些函式是

  1. malloc() 函式
    分配一個包含num個元素的陣列,每個元素的大小(以位元組為單位)為size。
  2. calloc() 函式
    分配一個包含num個位元組的陣列,並將其保留為未初始化狀態。
  3. realloc() 函式
    重新分配記憶體,將其擴充套件到newsize。

1. malloc() 函式

此函式在“stdlib.h”標頭檔案中定義。它分配一個所需大小的記憶體塊,並返回一個void指標。

void *malloc (size)

size引數指的是以位元組為單位的記憶體塊。要為指定的的資料型別分配記憶體,需要使用型別轉換運算子。例如,以下程式碼片段分配了儲存int型別所需的記憶體。

int *ptr;
ptr = (int * ) malloc (sizeof (int));

這裡我們需要定義一個指向字元的指標,而無需定義需要多少記憶體,然後根據需要,我們可以分配記憶體。

示例

在此示例中,我們使用malloc()函式分配儲存字串所需的記憶體(而不是宣告固定大小的char陣列) -

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(){

   char *name;
   name = (char *) malloc(strlen("TutorialsPoint"));

   strcpy(name, "TutorialsPoint");
   
   if(name == NULL) {
      fprintf(stderr, "Error - unable to allocate required memory\n");
   } else {
      printf("Name = %s\n", name );
   }
}

輸出

編譯並執行上述程式碼時,將產生以下輸出 -

Name = TutorialsPoint

2. calloc() 函式

C庫函式"calloc"(代表連續分配)分配請求的記憶體並返回指向它的指標。

void *calloc(n, size);

其中"n"是要分配的元素數量,"size"是每個元素的位元組大小。

以下程式碼片段分配了儲存10個整數型別所需的記憶體。

int *ptr;
ptr = (int *) calloc(25, sizeof(int));

3. realloc() 函式

C語言中的realloc()函式用於動態更改先前分配的記憶體的記憶體分配。您可以透過呼叫realloc()函式來增加或減少已分配記憶體塊的大小。

 
void *realloc(*ptr, size);

第一個引數"ptr"是指向記憶體塊的指標,該記憶體塊先前已使用malloc、callocrealloc分配,需要重新分配。

動態記憶體分配技術廣泛用於複雜的線性資料結構和非線性資料結構,例如連結列表和樹,這些結構用於作業系統軟體。

按引用傳遞引數

當函式按引用呼叫時,傳遞的是實際引數變數的地址,而不是它們的值。

將指標傳遞給函式有兩個優點 -

首先,它克服了按值傳遞的限制。對被呼叫函式內部值所做的更改會直接在指標中儲存的地址處進行。因此,我們可以從一個作用域操作另一個作用域中的變數。

其次,它還克服了函式只能返回一個表示式的限制。透過傳遞指標,函式處理的效果直接發生在地址處。其次,如果我們返回陣列或結構體變數的指標,則可以返回多個值。

示例

以下函式接收兩個變數的引用,這些變數的值需要交換。

/* function definition to swap the values */

int swap(int *x, int *y){
   int z;
   z = *x;    /* save the value at address x */
   *x = *y;   /* put y into x */
   *y = z;    /* put z into y */
  
   return 0;
}

示例

main()函式有兩個變數"a"和"b",它們的地址作為引數傳遞給swap()函式。

#include <stdio.h>

int swap(int *x, int *y);

int main(){

   /* local variable definition */
   int a = 10;
   int b = 20;
 
   printf("Before swap, value of a : %d\n", a);
   printf("Before swap, value of b : %d\n", b);
 
   /* calling a function to swap the values */
   swap(&a, &b);
 
   printf("After swap, value of a: %d\n", a);
   printf("After swap, value of b: %d\n", b);
 
   return 0;
}

輸出

執行後,將產生以下輸出 -

Before swap, value of a: 10
Before swap, value of b: 20
After swap, value of a: 20
After swap, value of b: 10

在此程式中,我們能夠在函式作用域之外交換兩個變數的值,這些變數已作為引數傳遞給該函式,並且我們克服了函式只能傳遞一個表示式的限制。

將陣列傳遞給函式

讓我們利用這些特性來按引用傳遞陣列。在main()函式中,我們宣告一個數組並將它的地址傳遞給max()函式。

max()函式使用指標遍歷陣列,並將陣列中最大的數字返回給main()函式。

示例

請看以下示例 -

#include <stdio.h>

int max(int *arr, int length);

int main(){
    
   int arr[] = {10, 34, 21, 78, 5};
   int length = sizeof(arr)/sizeof(int);

   int maxnum = max(arr, length);
      printf("max: %d", maxnum);
}

int max(int *arr, int length){

   int max = *arr;
        
   for (int i = 0; i < length; i++){   
      printf("arr[%d]: %d\n", i, (*arr));
        
      if ((*arr)>max)
         max = (*arr);
      arr++;
   }
   return max;
}

輸出

執行程式碼並檢查其輸出 -

arr[0]: 10
arr[1]: 34
arr[2]: 21
arr[3]: 78
arr[4]: 5
max: 78

max()函式從main()函式中接收陣列的地址,儲存在指標"arr"中。每次遞增時,它都會指向原始陣列中的下一個元素。

從函式返回多個值

在C語言中,函式只能有一個return語句來一次返回一個值。藉助C指標,您可以透過按引用傳遞引數從函式返回多個值。

示例

以下示例演示瞭如何藉助C指標返回多個值。

#include <stdio.h>

// Creating a function to find
// addition and subtraction
// of two numbers
void funAddSub(int a, int b, int* add, int* sub) {
  *add = a + b;
  *sub = a - b;
}

int main() {
  int num1 = 10;
  int num2 = 3;

  // Variables to store results
  int res1, res2;

  // Calling function to get add and sub
  // by passing the address of res1 and res2
  funAddSub(num1, num2, &res1, &res2);

  // Printing the result
  printf("Addition is %d and subtraction is %d", res1, res2);

  return 0;
}

輸出

Addition is 13 and subtraction is 7
廣告