C語言中的指標



什麼是C語言中的指標?

C指標是一種派生資料型別,用於儲存另一個變數的地址,也可以用於訪問和操作儲存在該位置的變數資料。指標被認為是派生資料型別。

使用指標,您可以訪問和修改記憶體中位於的位置的資料,在函式之間有效地傳遞資料,並建立動態資料結構,如連結列表、樹和圖。

指標宣告

要宣告一個指標,請使用**間接訪問運算子(*)**後跟資料型別。

語法

指標變數宣告的一般形式為:

type *var-name;

這裡,type是指標的基本型別;它必須是有效的C資料型別,而var-name是指標變數的名稱。用於宣告指標的星號*與用於乘法的星號相同。但是,在此語句中,星號用於將變數指定為指標。

有效指標變數宣告示例

看看一些有效的指標宣告:

int    *ip;    /* pointer to an integer */
double *dp;    /* pointer to a double */
float  *fp;    /* pointer to a float */
char   *ch     /* pointer to a character */

所有指標的值的實際資料型別,無論是整數、浮點數、字元還是其他型別,都是相同的,一個表示記憶體地址的長十六進位制數。不同資料型別指標之間的唯一區別是指標指向的變數常量的資料型別。

指標初始化

宣告指標變數後,需要使用**取地址(&)運算子**將其初始化為另一個變數的地址。此過程稱為**引用指標**。

語法

以下是初始化指標變數的語法:

pointer_variable = &variable;

示例

這是一個指標初始化的示例:

int x = 10;
int *ptr = &x;

這裡,x是一個整數變數,ptr是一個整數指標。指標ptr被初始化為x

引用和解引用指標

指標引用記憶體中的一個位置。獲取儲存在該位置的值稱為**解引用指標**。

在C語言中,瞭解以下兩個運算子在指標機制中的作用非常重要:

  • &運算子 - 它也被稱為“取地址運算子”。它用於引用,這意味著獲取現有變數的地址(使用&)以設定指標變數。
  • *運算子 - 它也被稱為“解引用運算子”。使用*運算子執行**解引用**指標以獲取指標指向的記憶體地址中的值。

指標用於按引用傳遞引數。如果程式設計師希望函式對引數的修改對函式的呼叫者可見,這將很有用。這對於從函式返回多個值也很有用。

使用指標訪問和操作值

可以透過使用指標變數來訪問和操作指標指向的變數的值。您需要在指標變數前使用星號(*)來訪問和操作變數的值。

示例

在下面的示例中,我們獲取一個整數變數及其初始值,並將其更改為新值。

#include <stdio.h>

int main() {
  int x = 10;

  // Pointer declaration and initialization
  int * ptr = & x;

  // Printing the current value
  printf("Value of x = %d\n", * ptr);

  // Changing the value
  * ptr = 20;

  // Printing the updated value
  printf("Value of x = %d\n", * ptr);

  return 0;
}

輸出

Value of x = 10
Value of x = 20

如何使用指標?

要在C語言中使用指標,您需要宣告一個指標變數,然後將其初始化為另一個變數的地址,然後您可以透過解引用來使用它以獲取和更改指標指向的變數的值。

您可以將指標與任何型別的變數一起使用,例如整數、浮點數、字串等。您還可以將指標與派生資料型別一起使用,例如陣列結構體聯合體等。

示例

在下面的示例中,我們使用指標來獲取不同型別變數的值。

#include <stdio.h>

int main() {
  int x = 10;
  float y = 1.3f;
  char z = 'p';

  // Pointer declaration and initialization
  int * ptr_x = & x;
  float * ptr_y = & y;
  char * ptr_z = & z;

  // Printing the values
  printf("Value of x = %d\n", * ptr_x);
  printf("Value of y = %f\n", * ptr_y);
  printf("Value of z = %c\n", * ptr_z);
  
  return 0;
}

輸出

Value of x = 10
Value of y = 1.300000
Value of z = p

指標變數的大小

指標變數佔用的記憶體(或大小)不取決於它指向的變數的型別。指標的大小取決於系統架構。

示例

在下面的示例中,我們列印不同型別指標的大小

#include <stdio.h>

int main() {
  int x = 10;
  float y = 1.3f;
  char z = 'p';

  // Pointer declaration and initialization
  int * ptr_x = & x;
  float * ptr_y = & y;
  char * ptr_z = & z;

  // Printing the size of pointer variables
  printf("Size of integer pointer : %lu\n", sizeof(ptr_x));
  printf("Size of float pointer : %lu\n", sizeof(ptr_y));
  printf("Size of char pointer : %lu\n", sizeof(ptr_z));
  
  return 0;
}

輸出

Size of integer pointer : 8
Size of float pointer : 8
Size of char pointer : 8

C指標示例

練習以下示例以學習指標的概念:

示例1:在C語言中使用指標

以下示例演示瞭如何在C語言中使用&*運算子執行與指標相關的操作:

#include <stdio.h>

int main(){

   int  var = 20;   /* actual variable declaration */
   int  *ip;        /* pointer variable declaration */

   ip = &var;   /* store address of var in pointer variable*/

   printf("Address of var variable: %p\n", &var);

   /* address stored in pointer variable */
   printf("Address stored in ip variable: %p\n", ip);

   /* access the value using the pointer */
   printf("Value of *ip variable: %d\n", *ip );

   return 0;
}

輸出

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

Address of var variable: 0x7ffea76fc63c
Address stored in ip variable: 0x7ffea76fc63c
Value of *ip variable: 20

示例:列印整數的值和地址

我們將宣告一個int變數並顯示其值和地址:

#include <stdio.h>

int main(){

   int var = 100;
   
   printf("Variable: %d \t Address: %p", var, &var);
   
   return 0;   
}

輸出

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

Variable: 100   Address: 0x7ffc62a7b844

示例:整數指標

在此示例中,var的地址使用&運算子儲存在intptr變數中

#include <stdio.h>

int main(){

   int var = 100;
   int *intptr = &var;
   
   printf("Variable: %d \nAddress of Variable: %p \n\n", var, &var);
   printf("intptr: %p \nAddress of intptr: %p \n\n", intptr, &intptr);
   
   return 0;
}

輸出

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

Variable: 100 
Address of Variable: 0x7ffdcc25860c 

intptr: 0x7ffdcc25860c 
Address of intptr: 0x7ffdcc258610 

示例5

現在讓我們以一個浮點變數為例,並找到它的地址:

#include <stdio.h>

int main(){

   float var1 = 10.55;
   
   printf("var1: %f \n", var1);
   printf("Address of var1: %d", &var1);
}

輸出

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

var1: 10.550000 
Address of var1: 1512452612

我們可以看到此變數(任何型別的變數)的地址都是一個整數。因此,如果我們嘗試將其儲存在“float”型別的指標變數中,請檢視會發生什麼:

float var1 = 10.55;
int *intptr = &var1;

編譯器不接受此操作,並報告以下錯誤

initialization of 'int *' from incompatible pointer type 
'float *' [-Wincompatible-pointer-types]

注意:變數的型別及其指標的型別必須相同。

在C語言中,變數具有特定資料型別,這些資料型別定義了它們的大小以及它們如何儲存值。使用匹配型別(例如,float *)宣告指標可在指標與其指向的資料之間強制執行“型別相容性”。

C語言中不同資料型別佔用不同的記憶體空間。例如,一個“int”型別變數通常佔用4個位元組,而“float”型別變數可能佔用4或8個位元組,具體取決於系統。從指標新增或減去整數會根據它們指向的資料的大小在記憶體中移動指標。

示例:浮點數指標

在這個例子中,我們聲明瞭一個名為“floatptr”的“float *”型別的變數。

#include <stdio.h>

int main(){

   float var1 = 10.55;
   float *floatptr = &var1;
   
   printf("var1: %f \nAddress of var1: %p \n\n",var1, &var1);
   printf("floatptr: %p \nAddress of floatptr: %p \n\n", floatptr, &floatptr);
   printf("var1: %f \nValue at floatptr: %f", var1, *floatptr);
   
   return 0;
}

輸出

var1: 10.550000 
Address of var1: 0x7ffc6daeb46c 

floatptr: 0x7ffc6daeb46c 
Address of floatptr: 0x7ffc6daeb470 

指向指標的指標

我們可以有一個指標變數,它儲存另一個指標本身的地址。

Pointer Variable

在上圖中,“a”是一個普通的“int”型別變數,其指標為“x”。反過來,變數“y”儲存“x”的地址。

請注意,“y”被宣告為“int **”,表示它是一個指向另一個指標變數的指標。顯然,“y”將返回“x”的地址,而“*y”是“x”中的值(即“a”的地址)。

要從“y”獲取“a”的值,我們需要使用表示式“**y”。通常,“y”被稱為**指向指標的指標**。

示例

請看下面的例子:

#include <stdio.h>

int main(){

   int var = 10;
   int *intptr = &var;
   int **ptrptr = &intptr;
   
   printf("var: %d \nAddress of var: %d \n\n",var, &var);
   printf("inttptr: %d \nAddress of inttptr: %d \n\n", intptr, &intptr);
   printf("var: %d \nValue at intptr: %d \n\n", var, *intptr);
   printf("ptrptr: %d \nAddress of ptrtptr: %d \n\n", ptrptr, &ptrptr);
   printf("intptr: %d \nValue at ptrptr: %d \n\n", intptr, *ptrptr);
   printf("var: %d \n*intptr: %d \n**ptrptr: %d", var, *intptr, **ptrptr);
   
   return 0;
}

輸出

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

var: 10 
Address of var: 951734452 

inttptr: 951734452 
Address of inttptr: 951734456 

var: 10 
Value at intptr: 10 

ptrptr: 951734456 
Address of ptrtptr: 951734464 
intptr: 951734452 
Value at ptrptr: 951734452 

var: 10 
*intptr: 10 
**ptrptr: 10

您也可以擁有**指向陣列的指標**,以及使用**struct**定義的派生型別。指標具有重要的應用。它們在透過傳遞引用呼叫函式時使用。指標還有助於克服函式只能返回單個值的限制。使用指標,您可以獲得返回多個值或陣列的效果。

空指標

如果您沒有確切的地址要分配,那麼始終建議將空值分配給指標變數。這在變數宣告時完成。分配了NULL的指標稱為**空**指標。

NULL指標是一個常量,其值為“0”,在多個標準庫中定義。

示例

考慮以下程式:

#include <stdio.h>

int main(){

   int *ptr = NULL;

   printf("The value of ptr is : %x\n", ptr);
 
   return 0;
}

輸出

當以上程式碼編譯並執行時,會產生以下結果:

The value of ptr is 0

在大多數作業系統中,程式不允許訪問地址“0”處的記憶體,因為該記憶體由作業系統保留。

記憶體地址“0”具有特殊的意義;它表示指標不打算指向可訪問的記憶體位置。但按照慣例,如果指標包含空(零)值,則假定它不指向任何內容。

要檢查空指標,您可以使用如下所示的**if**語句:

if(ptr)     /* succeeds if p is not null */
if(!ptr)    /* succeeds if p is null */

變數的地址

如您所知,每個變數都是一個記憶體位置,每個記憶體位置都有其定義的地址,可以使用地址運算子(&)訪問,該運算子表示記憶體中的地址。

示例

考慮以下示例,它列印定義的變數的地址:

#include <stdio.h>

int main(){

   int  var1;
   char var2[10];

   printf("Address of var1 variable: %x\n", &var1);
   printf("Address of var2 variable: %x\n", &var2);

   return 0;
}

輸出

當以上程式碼編譯並執行時,它將列印變數的地址:

Address of var1 variable: 61e11508
Address of var2 variable: 61e1150e

指標詳解

指標有很多但簡單的概念,它們對C程式設計非常重要。以下重要的指標概念應該對任何C程式設計師都清晰:

序號 概念及描述
1 指標運算

指標可以使用四種算術運算子:++、--、+、-

2 指標陣列

您可以定義陣列來儲存多個指標。

3 指向指標的指標

C允許您在指標上擁有指標,依此類推。

4 在C語言中將指標傳遞給函式

透過引用或透過地址傳遞引數使被呼叫函式能夠在呼叫函式中更改傳遞的引數。

5 在C語言中從函式返回指標

C允許函式返回指向區域性變數、靜態變數和動態分配記憶體的指標。

廣告