溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

c++中數(shù)組與指針是什么

發(fā)布時間:2020-08-15 11:44:27 來源:億速云 閱讀:151 作者:小新 欄目:開發(fā)技術(shù)

這篇文章將為大家詳細(xì)講解有關(guān)c++中數(shù)組與指針是什么,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。

1.數(shù)組

數(shù)組大?。ㄔ貍€數(shù))一般在編譯時決定,也有少部分編譯器可以運(yùn)行時動態(tài)決定數(shù)組大小,比如icpc(Intel C++編譯器)。

1.1數(shù)組名的意義

數(shù)組名的本質(zhì)是一個文字常量,代表數(shù)組第一個元素的地址和數(shù)組的首地址。數(shù)組名本身不是一個變量,不可以尋址,且不允許為數(shù)組名賦值。假設(shè)定義數(shù)組:

int A[10];

那么再定義一個引用:

int* &r=A;

這是錯誤的寫法,因為變量A是一個文字常量,不可尋址。如果要建立數(shù)組A的引用,應(yīng)該這樣定義:

int* const &r=A;

此時,現(xiàn)在數(shù)據(jù)區(qū)開辟一個無名臨時變量,將數(shù)組A代表的地址常量拷貝到該變量中,再將常引用r與此變量進(jìn)行綁定。此外,定義一個數(shù)組A,則A、&A[0]、A+0是等價的。

在sizeof()運(yùn)算中,數(shù)組名代表的是全體數(shù)組元素,而不是某個單個元素。例如,定義int A[5],生成Win32的程序,sizeof(A)就等于5*sizeof(int)=5*4=20。示例程序如下。

#include <iostream>
using namespace std;

int main()
{
int A[4]={1,2,3,4};
int B[4]={5,6,7,8};
int (&rA)[4]=A; //建立數(shù)組A的引用

cout<<"A:"<<A<<endl;
cout<<"&A:"<<&A<<endl;
cout<<"A+1:"<<A+1<<endl;
cout<<"&A+1:"<<&A+1<<endl;
cout<<"B:"<<B<<endl;
cout<<"rA:"<<rA<<endl;
cout<<"&rA:"<<&rA<<endl;
}

運(yùn)行結(jié)果:

A:0013F76C
&A:0013F76C
A+1:0013F770
&A+1:0013F77C
B:0013F754
rA:0013F76C
&rA:0013F76C

閱讀以上程序,注意如下幾點。

(1)A與&A的結(jié)果在數(shù)值上是一樣的,但是A與&A的數(shù)據(jù)類型卻不同。A的類型是int[4],&A的類型則是int(*)[4]。它們在概念上是不一樣的,這就直接導(dǎo)致A+1與&A+1的結(jié)果完全不一樣。

(2)為變量建立引用的語法格式是type& ref,因為數(shù)組A的類型是int[4],因此為A建立引用的是int (&rA)[4]=A;

1.2數(shù)組的初始化

定義數(shù)組的時候,為數(shù)組元素賦初值,叫作數(shù)組的初始化??梢詾橐痪S數(shù)組指定初值,也可以為多維數(shù)組指定初值。例如。

Int A[5]={}; //定義長度為5的數(shù)組,所有數(shù)組元素的值都為0
int A[]={1,2,3}; //定義長度為3的數(shù)組,數(shù)組元素分別為1,2,3
int A[5]={1,2}; //定義長度為5的數(shù)組,A[0],A[1]分別為1,2,其他值均為0
int A[][2]={{1,2},{3,4},{5,6}}; //定義一個類型為int[3][2]的二維數(shù)組
int A[][2]={{1},{1},{1}}; //定義一個類型為int[3][2]的二維數(shù)組,A[0][0]、A[1][0]、A[2][0]三個元素的值為1,其他元素的值均為0

//以下是幾種錯誤的初始化方法
int A[3]={1,2,3,4}; //初始化項的個數(shù)超過數(shù)組的長度 
int A[3]={1,,3}; //不允許中間跳過某項

2.指針

2.1指針的定義

指針是用來存放地址值的變量,相應(yīng)的數(shù)據(jù)類型成為指針類型。在32位平臺上,任何指針類型所占用的空間都是都是4字節(jié)。比如sizeof(int*)、sizeof(double*)、sizeof(float*)等的值都為4。

2.2定義指針的形式

定義指針的形式是:type* p,其中type是指針?biāo)赶驅(qū)ο蟮臄?shù)據(jù)類型,而*則是指針的標(biāo)志,p是指針變量的名字。由于C++中允許定義復(fù)合數(shù)據(jù)類型,因此指向復(fù)合數(shù)據(jù)類型對象的指針的定義方式可能較為復(fù)雜。理解指針,關(guān)鍵是理解指針的類型和指針?biāo)赶驍?shù)據(jù)的類型。例如:

int (*p)[5]; //指針p的類型是int(*)[5],指針?biāo)赶虻臄?shù)據(jù)類型是int[5]
int* p[5]; //p是有5個分量的指針數(shù)組,每個分量的類型都是int*(指向int的指針)
int** p; //指針p的類型是int**,p指向的類型是int*,p是指向指針的指針

2.3指針的初始化

定義指針變量之后,指針變量的值一般是隨機(jī)值,這樣的值不是合法訪問的地址。指針變量值的合法化途徑通常有兩個,
一是顯示置空,二是讓指針指向一個已經(jīng)存在的變量,三是為指針動態(tài)申請內(nèi)存空間。如下:

//顯示置空
int *p=NULL;

//將指針指向某個變量
int i;
int *p=&i;

//動態(tài)申請內(nèi)存空間
int* p=new int[10];

2.4指針可以參與的運(yùn)算

由于指針是一個變量,所以指針可以參與一些運(yùn)算。假設(shè)定義指針int* p,指針p能夠參與的運(yùn)算有:
(1)解引用運(yùn)算,即獲取指針?biāo)傅膬?nèi)存地址處的數(shù)據(jù),表達(dá)式為*p,如果指針指向的是一個結(jié)構(gòu)或者類的對象,那么訪問對象成員有兩種方式:(*p).mem或p->mem。

(2)取地址運(yùn)算,即獲取指針變量的地址,表達(dá)式為&p,其數(shù)據(jù)類型為int**;

(3)指針與整數(shù)相加減。表達(dá)式p+i(或者p-i),實際上是讓指針遞增或遞減地移動i個int型變量的距離。

(4)兩個指針相減,如p-q,其結(jié)果是兩個指針?biāo)鎯Φ牡刂分g的int型數(shù)據(jù)的個數(shù)。

2.5注意指針的有效性

使用指針的關(guān)鍵就是讓指針變量指向一個它可以合法訪問的內(nèi)存地址,如果不知道它指向何處,請置為空指針NULL或者((void*)0)。

在某些情況下,指針的值開始是合法的,以后隨著某些操作的進(jìn)行,它變成了非法的值。考察如下程序。

#include <iostream>
using namespace std;

int* pPointer;
void SomeFunction()
{
int nNumber=25;
pPointer=&nNumber; //將指針pPointer指向nNumber
}

void UseStack()
{
int arr[100]={};
}

int main()
{
SomeFunction();
UseStack();
cout<<"value of *pPointer:"<<*pPointer<<endl;
}

輸出結(jié)果是0,并非想象中的25。原因是函數(shù)SomeFunction()運(yùn)行結(jié)束之后,局部變量nNumber已經(jīng)被清空,其占有的空間在離開函數(shù)后歸還給系統(tǒng),之后又分配給函數(shù)UseStack()中的局部變量arr。因此指針pNumber的解引用后的值變成了0。所以,要想正確的使用指針,必須保證指針?biāo)赶騿卧挠行浴?/p>

3.數(shù)組與指針的關(guān)系

數(shù)組名代表數(shù)組的首地址,而數(shù)組A的某個元素A[i]可以解釋成*(A+i),所以數(shù)組名本身可以理解為一個指針(地址),一個指針常量。所以,在很多情況下,數(shù)組與指針的用法是相同的,但是數(shù)組與指針本質(zhì)上存在一些重要的區(qū)別。

(1)數(shù)組空間是靜態(tài)分配的,編譯時決定大小。而指針在定義時,可以沒有合法訪問的地址空間,也就是野指針。

(2)數(shù)組名代表一個指針常量,企圖改變數(shù)組名所代表的地址的操作都是非法的。例如如下代碼:

int arr[5]={0,1,2,3,4};
arr++; //編譯錯誤

(3)函數(shù)形參中的數(shù)組被解釋為指針。考察如下程序:

void show0(int A[])
{
A++;
cout<<A[0]<<endl;
}

void show1(int A[5])
{
A++;
cout<<A[0]<<endl;
}

int main()
{
int d[5]={1,2,3,4,5};
show0(d);
show1(d);
}

以上程序編譯通過并輸出2和2。程序中形參數(shù)組A可以進(jìn)行自增運(yùn)算,改變了自身的值,這個說明了形參數(shù)組A被當(dāng)作指針看待。之所以這樣處理,原因有兩個,一是C++語言不對數(shù)組的下標(biāo)作越界檢查,因此可以忽略形參數(shù)組的長度;二是數(shù)組作整體進(jìn)行傳遞時,會有較大的運(yùn)行時開銷,為了提高程序運(yùn)行效率,將數(shù)組退化成了指針。

(4)如果函數(shù)的形參是數(shù)組的引用,那么數(shù)組的長度將被作為類型的一部分。實際上,對數(shù)組建立引用,就是對數(shù)組的首地址建立一個常引用。由于引用是C++引入的新機(jī)制,所以在處理引用時使用了一些與傳統(tǒng)C語言不同的規(guī)范。在傳統(tǒng)的C語言中,對數(shù)組的下標(biāo)是不做越界檢查,因此在函數(shù)的參數(shù)說明中,int[5]和int[6]都被理解為int[](也就是int*),C++語言也沿用了這種處理方式。但是,int(&)[5]與int(&)[6]被認(rèn)為是不同的數(shù)據(jù)類型,在實參與形參的匹配過程作嚴(yán)格檢查??疾烊缦鲁绦?。

#include <iostream>
using namespace std;

void show(int(&A)[5])
{
cout<<"type is int(&)[5]"<<endl;
}

void show(int(&A)[6])
{
cout<<"type is int(&)[5]"<<endl;
}

int main()
{
int d[5]={1,2,3,4,5};
show(d);
}

程序結(jié)果:

type is int(&)[5]

(5)在概念上,指針同一維數(shù)組相對應(yīng)。多維數(shù)組是存儲在連續(xù)的存儲空間,而將多維數(shù)組當(dāng)做一維數(shù)據(jù)看待時,可以有不同的分解方式。考察如下程序。

#include <iostream>
using namespace std;

void show1(int A[],int n)
{
for(int i=0;i<n;++i)
cout<<A[i]<<" ";
}

void show2(int A[][5],int n)
{
for(int i=0;i<n;++i)
show1(A[i],5);
}

void show3(int A[][4][5],int n)
{
for(int i=0;i<n;++i)
show2(A[i],4);
}

int main()
{
int d[3][4][5];
int i,j,k,m=0;
for(int i=0;i<3;++i)
for(int j=0;j<4;++j)
for(int k=0;k<5;++k)
d[i][j][k]=m++;

show1((int*)d,3*4*5);
cout<<endl;
show2((int(*)[5])d,3*4);
cout<<endl;
show3(d,3);
}

程序運(yùn)行結(jié)果可以看出,以下三條輸出語句的數(shù)據(jù)結(jié)果是相同的。

show1((int *)d,3*4*5);
show2((int(*)[5])d,3*4);
show3(d,3);

它們的輸出結(jié)果完全一樣,即從0到59。這說明把3維數(shù)組d當(dāng)作一維數(shù)組看待,至少可以有以下3中不同的分解方式:

a.數(shù)據(jù)類型為int,元素個數(shù)為3*4*5=60;
b.數(shù)據(jù)類型為int[5],元素個數(shù)為3*4=12;
c.數(shù)據(jù)類型為int[4][5],元素個數(shù)為3。

所以,可以將多維數(shù)組看做“數(shù)組的數(shù)組”。在將多為數(shù)組轉(zhuǎn)換為指針的時候,一定要注意多為數(shù)組的分解方式,以便進(jìn)行正確的類型轉(zhuǎn)換。

(6)字符數(shù)組與字符指針的區(qū)別。
字符數(shù)組字符指針在形式上很接近,但在內(nèi)存空間的分配和使用上還是有重大的差別。如前所述,數(shù)組名并不是一個運(yùn)行實體,它本身不能被尋址。而指針是一個變量(運(yùn)行時實體),可以被尋址,它所指向的空間是否合法要在運(yùn)行時決定。錯誤地使用指針將導(dǎo)致對內(nèi)存空間的非法訪問??疾烊缦鲁绦?。

#include <iostream>
using namespace std;
int main()
{
char s[]="abc"; //s是字符數(shù)組,空間分配在棧上。對字符數(shù)組元素的修改是合法的
char *p="abc"; 
s[0]='x';
cout<<s<<endl;
//p[0]='x'; //此句編譯出錯,指針指向常量區(qū)的字符串,對字符串常量的修改是非法的
cout<<p<<endl;
}

程序輸出結(jié)果:

xbc
abc

關(guān)于c++中數(shù)組與指針是什么就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI