D編程 指針(Pointers)

2021-09-01 11:09 更新

D編程指針既簡單又有趣,使用指針可以更輕松地執(zhí)行某些任務,而沒有它們則無法執(zhí)行其他任務(如動態(tài)內(nèi)存分配),一個簡單的指針如下所示。

Pointer in D

import std.stdio;
 
void main () { 
   int var1; 
   writeln("Address of var1 variable: ",&var1);  
   
   char var2[10]; 
   writeln("Address of var2 variable: ",&var2); 
}

編譯并執(zhí)行上述代碼后,將產(chǎn)生以下輸出-

Address of var1 variable: 7FFF52691928 
Address of var2 variable: 7FFF52691930

指針

指針是一個變量,其值是另一個變量的地址,像任何變量或常量一樣,必須先聲明一個指針,然后才能使用它。指針變量聲明的一般形式是-

type *var-name;

在這里, type 是指針的基本類型,它必須是有效的編程類型,并且 var-name 是指針變量的名稱,用于聲明指針的星號與用于乘法的星號相同,然而;在此語句中,星號用于將變量指定為指針。以下是有效的指針聲明-

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

所有指針的值的實際數(shù)據(jù)類型(無論是整數(shù),浮點數(shù),字符還是其他形式)都是相同的,即表示內(nèi)存地址的十六進制數(shù)字,不同數(shù)據(jù)類型的指針之間的唯一區(qū)別是指針指向的變量或常量的數(shù)據(jù)類型。

使用指針

當我們非常頻繁地使用指針時,很少有重要的操作。

  • 我們定義了一個指針變量
  • 將變量的地址分配給指針
  • 最終訪問指針變量中可用地址處的值。

這是通過使用一元運算符 * 完成的,該運算符返回位于變量操作數(shù)指定地址處的變量的值。以下示例利用這些操作-

import std.stdio; 

void main () { 
   int var=20;   //actual variable declaration. 
   int *ip;        //pointer variable
   ip=&var;   //store address of var in pointer variable  
   
   writeln("Value of var variable: ",var); 
   
   writeln("Address stored in ip variable: ",ip); 
   
   writeln("Value of *ip variable: ",*ip); 
}

編譯并執(zhí)行上述代碼后,將產(chǎn)生以下輸出-

Value of var variable: 20 
Address stored in ip variable: 7FFF5FB7E930 
Value of *ip variable: 20

空指針

在沒有確切地址要分配的情況下,最好將指針NULL分配給指針變量,這是在變量聲明時完成的,分配為null的指針稱為 null 指針。

空指針是在幾個標準庫(包括iostream)中定義的值為零的常量??紤]以下程序-

import std.stdio;

void main () { 
   int  *ptr=null; 
   writeln("The value of ptr is " , ptr) ;  
}

編譯并執(zhí)行上述代碼后,將產(chǎn)生以下輸出-

The value of ptr is null

在大多數(shù)操作系統(tǒng)上,不允許程序訪問地址0處的內(nèi)存,因為該內(nèi)存是由操作系統(tǒng)保留的,然而;存儲器地址0具有特殊的意義;它指示指針不旨在指向可訪問的存儲位置。

按照慣示例,如果指針包含空(零)值,則假定該指針不指向任何內(nèi)容。要檢查空指針,可以使用以下if語句-

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

因此,如果為所有未使用的指針賦予了空值,并且避免了使用空指針,則可以避免意外誤用未初始化的指針。

指針算術(shù)

可以在指針上使用四種算術(shù)運算符:++,--,+和-

為了理解指針算術(shù),讓我們考慮一個名為 ptr 的整數(shù)指針,該指針指向地址1000。假設32位整數(shù),讓我們對指針執(zhí)行以下算術(shù)運算-

ptr++ 

那么 ptr 將指向位置1004,因為每次ptr遞增時,它都指向下一個整數(shù)。該操作會將指針移動到下一個存儲位置,而不會影響該存儲位置的實際值。

如果 ptr 指向地址為1000的字符,則上述操作將指向位置1001,因為下一個字符將在1001處可用。

遞增指針

我們更喜歡在程序中使用指針而不是數(shù)組,因為變量指針可以遞增,這與數(shù)組名不同,因為數(shù)組名是常量指針,因此不能遞增。以下程序遞增變量指針以訪問數(shù)組的每個后續(xù)元素-

import std.stdio; 
 
const int MAX=3; 
 
void main () { 
   int var[MAX]=[10, 100, 200]; 
   int *ptr=&var[0];  

   for (int i=0; i < MAX; i++, ptr++) { 
      writeln("Address of var[" , i , "]=",ptr); 
      writeln("Value of var[" , i , "]=",*ptr); 
   } 
}

編譯并執(zhí)行上述代碼后,將產(chǎn)生以下輸出-

Address of var[0]=18FDBC 
Value of var[0]=10 
Address of var[1]=18FDC0 
Value of var[1]=100 
Address of var[2]=18FDC4 
Value of var[2]=200

指針與數(shù)組

指針和數(shù)組密切相關(guān),但是,指針和數(shù)組不能完全互換。如,考慮以下程序-

import std.stdio; 
 
const int MAX=3;
  
void main () { 
   int var[MAX]=[10, 100, 200]; 
   int *ptr=&var[0]; 
   var.ptr[2] =290; 
   ptr[0]=220;  
   
   for (int i=0; i < MAX; i++, ptr++) { 
      writeln("Address of var[" , i , "]=",ptr); 
      writeln("Value of var[" , i , "]=",*ptr); 
   } 
}

在上面的程序中,您可以看到var.ptr [2]設置第二個元素,而ptr [0]用來設置第零個元素,增量運算符可以與ptr一起使用,但不能與var一起使用。

編譯并執(zhí)行上述代碼后,將產(chǎn)生以下輸出-

Address of var[0]=18FDBC 
Value of var[0]=220 
Address of var[1]=18FDC0 
Value of var[1]=100 
Address of var[2]=18FDC4 
Value of var[2]=290

指針到指針

指向指針的指針是多種間接形式或指針鏈的形式。通常,指針包含變量的地址,當我們定義一個指向指針的指針時,第一個指針包含第二個指針的地址,該地址指向包含實際值的位置,如下所示。

C++ 指針到指針

作為指針的指針的變量必須這樣聲明。這是通過在其名稱前面放置一個額外的星號*來完成的。如以下是聲明指向int類型指針的語法-

int **var; 

當指向指針的指針間接指向目標值時,訪問該值需要兩次應用星號**運算符,如下面的示例所示-

import std.stdio;  

const int MAX=3;
  
void main () { 
   int var=3000; 
   writeln("Value of var :" , var); 
   
   int *ptr=&var; 
   writeln("Value available at *ptr :" ,*ptr); 
   
   int **pptr=&ptr; 
   writeln("Value available at **pptr :",**pptr); 
}

編譯并執(zhí)行上述代碼后,將產(chǎn)生以下輸出-

Value of var :3000 
Value available at *ptr :3000 
Value available at **pptr :3000

指針函數(shù)

D允許您將指針傳遞給函數(shù)。為此,它只是將函數(shù)參數(shù)聲明為指針類型。

下面的簡單示例將指針傳遞給函數(shù)。

import std.stdio; 
 
void main () { 
   //an int array with 5 elements. 
   int balance[5]=[1000, 2, 3, 17, 50]; 
   double avg; 
   
   avg=getAverage( &balance[0], 5 ) ; 
   writeln("Average is :" , avg); 
} 
 
double getAverage(int *arr, int size) { 
   int    i; 
   double avg, sum=0; 
   
   for (i=0; i < size; ++i) {
      sum += arr[i]; 
   } 
   
   avg=sum/size; 
   return avg; 
}

將以上代碼編譯在一起并執(zhí)行后,將產(chǎn)生以下輸出-

Average is :214.4 

返回指針

考慮以下函數(shù),該函數(shù)使用指針返回10個數(shù)字,表示第一個數(shù)組元素的地址。

import std.stdio;
  
void main () { 
   int *p=getNumber(); 
   
   for ( int i=0; i < 10; i++ ) { 
      writeln("*(p + " , i , ") : ",*(p + i)); 
   } 
} 
 
int * getNumber( ) { 
   static int r [10]; 
   
   for (int i=0; i < 10; ++i) {
      r[i]=i; 
   }
   
   return &r[0]; 
}

編譯并執(zhí)行上述代碼后,將產(chǎn)生以下輸出-

*(p + 0) : 0 
*(p + 1) : 1 
*(p + 2) : 2 
*(p + 3) : 3 
*(p + 4) : 4 
*(p + 5) : 5 
*(p + 6) : 6 
*(p + 7) : 7 
*(p + 8) : 8 
*(p + 9) : 9

指向數(shù)組指針

數(shù)組名稱是指向數(shù)組第一個元素的常量指針。因此,在聲明中-

double balance[50];

balance是指向&balance [0]的指針,它是數(shù)組balance的第一個元素的地址。因此,以下程序片段為p分配了balance的第一個元素的地址-

double *p; 
double balance[10]; 
 
p=balance;

將數(shù)組名稱用作常量指針是合法的,反之亦然。因此,*(balance + 4)是訪問balance [4]數(shù)據(jù)的合法方法。

一旦將第一個元素的地址存儲在p中,就可以使用* p,*(p + 1),*(p + 2)等訪問數(shù)組元素。以下示例顯示了上面討論的所有概念-

import std.stdio;
 
void main () { 
   //an array with 5 elements. 
   double balance[5]=[1000.0, 2.0, 3.4, 17.0, 50.0]; 
   double *p;  
   
   p=&balance[0]; 
  
   //output each array element's value  
   writeln("Array values using pointer " ); 
   
   for ( int i=0; i < 5; i++ ) { 
      writeln( "*(p + ", i, ") : ", *(p + i)); 
   } 
}

編譯并執(zhí)行上述代碼后,將產(chǎn)生以下輸出-

Array values using pointer  
*(p + 0) : 1000 
*(p + 1) : 2 
*(p + 2) : 3.4 
*(p + 3) : 17
*(p + 4) : 50


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號